mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge release branch 4.13 to master
* 4.13: Snapshot deletion issues (#3969) server: Cannot list affinity group if there are hosts dedicated… (#4025) server: Search zone-wide storage pool when allocation algothrim is firstfitleastconsumed (#4002)
This commit is contained in:
commit
b984184b7a
@ -56,5 +56,5 @@ public interface CapacityDao extends GenericDao<CapacityVO, Long> {
|
||||
|
||||
float findClusterConsumption(Long clusterId, short capacityType, long computeRequested);
|
||||
|
||||
List<Long> orderHostsByFreeCapacity(Long clusterId, short capacityType);
|
||||
List<Long> orderHostsByFreeCapacity(Long zoneId, Long clusterId, short capacityType);
|
||||
}
|
||||
|
||||
@ -903,20 +903,28 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> orderHostsByFreeCapacity(Long clusterId, short capacityTypeForOrdering){
|
||||
public List<Long> orderHostsByFreeCapacity(Long zoneId, Long clusterId, short capacityTypeForOrdering){
|
||||
TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||
PreparedStatement pstmt = null;
|
||||
List<Long> result = new ArrayList<Long>();
|
||||
StringBuilder sql = new StringBuilder(ORDER_HOSTS_BY_FREE_CAPACITY_PART1);
|
||||
if(clusterId != null) {
|
||||
sql.append("AND cluster_id = ?");
|
||||
}
|
||||
sql.append(ORDER_HOSTS_BY_FREE_CAPACITY_PART2);
|
||||
if (zoneId != null) {
|
||||
sql.append(" AND data_center_id = ?");
|
||||
}
|
||||
if (clusterId != null) {
|
||||
sql.append(" AND cluster_id = ?");
|
||||
}
|
||||
sql.append(ORDER_HOSTS_BY_FREE_CAPACITY_PART2);
|
||||
try {
|
||||
pstmt = txn.prepareAutoCloseStatement(sql.toString());
|
||||
pstmt.setShort(1, capacityTypeForOrdering);
|
||||
if(clusterId != null) {
|
||||
pstmt.setLong(2, clusterId);
|
||||
int index = 2;
|
||||
if (zoneId != null) {
|
||||
pstmt.setLong(index, zoneId);
|
||||
index ++;
|
||||
}
|
||||
if (clusterId != null) {
|
||||
pstmt.setLong(index, clusterId);
|
||||
}
|
||||
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
<bean id="dataStoreProviderManagerImpl" class="org.apache.cloudstack.storage.datastore.provider.DataStoreProviderManagerImpl" />
|
||||
<bean id="storageCacheManagerImpl" class="org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl" />
|
||||
<bean id="storageCacheRandomAllocator" class="org.apache.cloudstack.storage.cache.allocator.StorageCacheRandomAllocator" />
|
||||
<bean id="xenserverSnapshotStrategy" class="org.apache.cloudstack.storage.snapshot.XenserverSnapshotStrategy" />
|
||||
<bean id="defaultSnapshotStrategy" class="org.apache.cloudstack.storage.snapshot.DefaultSnapshotStrategy" />
|
||||
<bean id="bAREMETAL" class="org.apache.cloudstack.storage.image.format.BAREMETAL" />
|
||||
<bean id="dataMotionServiceImpl" class="org.apache.cloudstack.storage.motion.DataMotionServiceImpl" />
|
||||
<bean id="dataObjectManagerImpl" class="org.apache.cloudstack.storage.datastore.DataObjectManagerImpl" />
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
<bean id="ancientDataMotionStrategy" class="org.apache.cloudstack.storage.motion.AncientDataMotionStrategy" />
|
||||
<bean id="storageCacheManagerImpl" class="org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl" />
|
||||
<bean id="storageCacheRandomAllocator" class="org.apache.cloudstack.storage.cache.allocator.StorageCacheRandomAllocator" />
|
||||
<bean id="xenserverSnapshotStrategy" class="org.apache.cloudstack.storage.snapshot.XenserverSnapshotStrategy" />
|
||||
<bean id="defaultSnapshotStrategy" class="org.apache.cloudstack.storage.snapshot.DefaultSnapshotStrategy" />
|
||||
<bean id="bAREMETAL" class="org.apache.cloudstack.storage.image.format.BAREMETAL" />
|
||||
<bean id="dataMotionServiceImpl" class="org.apache.cloudstack.storage.motion.DataMotionServiceImpl" />
|
||||
<bean id="dataObjectManagerImpl" class="org.apache.cloudstack.storage.datastore.DataObjectManagerImpl" />
|
||||
|
||||
@ -21,7 +21,6 @@ import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
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.Event;
|
||||
@ -34,7 +33,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.jobs.AsyncJob;
|
||||
import org.apache.cloudstack.framework.jobs.dao.SyncQueueItemDao;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
@ -71,9 +69,8 @@ import com.cloud.utils.db.DB;
|
||||
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);
|
||||
public class DefaultSnapshotStrategy extends SnapshotStrategyBase {
|
||||
private static final Logger s_logger = Logger.getLogger(DefaultSnapshotStrategy.class);
|
||||
|
||||
@Inject
|
||||
SnapshotService snapshotSvr;
|
||||
@ -90,12 +87,8 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
||||
@Inject
|
||||
SnapshotDataFactory snapshotDataFactory;
|
||||
@Inject
|
||||
private SnapshotDao _snapshotDao;
|
||||
@Inject
|
||||
private SnapshotDetailsDao _snapshotDetailsDao;
|
||||
@Inject
|
||||
private SyncQueueItemDao _syncQueueItemDao;
|
||||
@Inject
|
||||
VolumeDetailsDao _volumeDetailsDaoImpl;
|
||||
|
||||
@Override
|
||||
@ -264,68 +257,147 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Snapshot.State.BackedUp.equals(snapshotVO.getState()) && !Snapshot.State.Error.equals(snapshotVO.getState()) &&
|
||||
if (!Snapshot.State.BackedUp.equals(snapshotVO.getState()) &&
|
||||
!Snapshot.State.Destroying.equals(snapshotVO.getState())) {
|
||||
throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + " due to it is in " + snapshotVO.getState() + " Status");
|
||||
}
|
||||
|
||||
// first mark the snapshot as destroyed, so that ui can't see it, but we
|
||||
// may not destroy the snapshot on the storage, as other snapshots may
|
||||
// depend on it.
|
||||
Boolean deletedOnSecondary = deleteOnSecondaryIfNeeded(snapshotId);
|
||||
boolean deletedOnPrimary = deleteOnPrimaryIfNeeded(snapshotId);
|
||||
|
||||
if (deletedOnPrimary) {
|
||||
s_logger.debug(String.format("Successfully deleted snapshot (id: %d) on primary storage.", snapshotId));
|
||||
} else {
|
||||
s_logger.debug(String.format("The snapshot (id: %d) could not be found/deleted on primary storage.", snapshotId));
|
||||
}
|
||||
if (null != deletedOnSecondary && deletedOnSecondary) {
|
||||
s_logger.debug(String.format("Successfully deleted snapshot (id: %d) on secondary storage.", snapshotId));
|
||||
}
|
||||
return (deletedOnSecondary != null) && deletedOnSecondary || deletedOnPrimary;
|
||||
}
|
||||
|
||||
private boolean deleteOnPrimaryIfNeeded(Long snapshotId) {
|
||||
SnapshotVO snapshotVO;
|
||||
boolean deletedOnPrimary = false;
|
||||
snapshotVO = snapshotDao.findById(snapshotId);
|
||||
SnapshotInfo snapshotOnPrimaryInfo = snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Primary);
|
||||
if (snapshotVO != null && snapshotVO.getState() == Snapshot.State.Destroyed) {
|
||||
deletedOnPrimary = deleteSnapshotOnPrimary(snapshotId, snapshotOnPrimaryInfo);
|
||||
} else {
|
||||
// Here we handle snapshots which are to be deleted but are not marked as destroyed yet.
|
||||
// This may occur for instance when they are created only on primary because
|
||||
// snapshot.backup.to.secondary was set to false.
|
||||
if (snapshotOnPrimaryInfo == null) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(String.format("Snapshot (id: %d) not found on primary storage, skipping snapshot deletion on primary and marking it destroyed", snapshotId));
|
||||
}
|
||||
snapshotVO.setState(Snapshot.State.Destroyed);
|
||||
snapshotDao.update(snapshotId, snapshotVO);
|
||||
deletedOnPrimary = true;
|
||||
} else {
|
||||
SnapshotObject obj = (SnapshotObject) snapshotOnPrimaryInfo;
|
||||
try {
|
||||
obj.processEvent(Snapshot.Event.DestroyRequested);
|
||||
deletedOnPrimary = deleteSnapshotOnPrimary(snapshotId, snapshotOnPrimaryInfo);
|
||||
if (!deletedOnPrimary) {
|
||||
obj.processEvent(Snapshot.Event.OperationFailed);
|
||||
} else {
|
||||
obj.processEvent(Snapshot.Event.OperationSucceeded);
|
||||
}
|
||||
} catch (NoTransitionException e) {
|
||||
s_logger.debug("Failed to set the state to destroying: ", e);
|
||||
deletedOnPrimary = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return deletedOnPrimary;
|
||||
}
|
||||
|
||||
private Boolean deleteOnSecondaryIfNeeded(Long snapshotId) {
|
||||
Boolean deletedOnSecondary = null;
|
||||
SnapshotInfo snapshotOnImage = snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Image);
|
||||
if (snapshotOnImage == null) {
|
||||
s_logger.debug("Can't find snapshot on backup storage, delete it in db");
|
||||
snapshotDao.remove(snapshotId);
|
||||
return true;
|
||||
}
|
||||
|
||||
SnapshotObject obj = (SnapshotObject)snapshotOnImage;
|
||||
try {
|
||||
obj.processEvent(Snapshot.Event.DestroyRequested);
|
||||
List<VolumeDetailVO> volumesFromSnapshot;
|
||||
volumesFromSnapshot = _volumeDetailsDaoImpl.findDetails("SNAPSHOT_ID", String.valueOf(snapshotId), null);
|
||||
|
||||
if (volumesFromSnapshot.size() > 0) {
|
||||
try {
|
||||
obj.processEvent(Snapshot.Event.OperationFailed);
|
||||
} catch (NoTransitionException e1) {
|
||||
s_logger.debug("Failed to change snapshot state: " + e1.toString());
|
||||
s_logger.debug(String.format("Can't find snapshot [snapshot id: %d] on secondary storage", snapshotId));
|
||||
} else {
|
||||
SnapshotObject obj = (SnapshotObject)snapshotOnImage;
|
||||
try {
|
||||
deletedOnSecondary = deleteSnapshotOnSecondaryStorage(snapshotId, snapshotOnImage, obj);
|
||||
if (!deletedOnSecondary) {
|
||||
s_logger.debug(
|
||||
String.format("Failed to find/delete snapshot (id: %d) on secondary storage. Still necessary to check and delete snapshot on primary storage.",
|
||||
snapshotId));
|
||||
} else {
|
||||
s_logger.debug(String.format("Snapshot (id: %d) has been deleted on secondary storage.", snapshotId));
|
||||
}
|
||||
throw new InvalidParameterValueException("Unable to perform delete operation, Snapshot with id: " + snapshotId + " is in use ");
|
||||
} catch (NoTransitionException e) {
|
||||
s_logger.debug("Failed to set the state to destroying: ", e);
|
||||
// deletedOnSecondary remain null
|
||||
}
|
||||
} catch (NoTransitionException e) {
|
||||
s_logger.debug("Failed to set the state to destroying: ", e);
|
||||
return false;
|
||||
}
|
||||
return deletedOnSecondary;
|
||||
}
|
||||
|
||||
try {
|
||||
boolean result = deleteSnapshotChain(snapshotOnImage);
|
||||
obj.processEvent(Snapshot.Event.OperationSucceeded);
|
||||
if (result) {
|
||||
//snapshot is deleted on backup storage, need to delete it on primary storage
|
||||
SnapshotDataStoreVO snapshotOnPrimary = snapshotStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
|
||||
if (snapshotOnPrimary != null) {
|
||||
SnapshotInfo snapshotOnPrimaryInfo = snapshotDataFactory.getSnapshot(snapshotId, DataStoreRole.Primary);
|
||||
long volumeId = snapshotOnPrimary.getVolumeId();
|
||||
VolumeVO volumeVO = volumeDao.findById(volumeId);
|
||||
if (((PrimaryDataStoreImpl)snapshotOnPrimaryInfo.getDataStore()).getPoolType() == StoragePoolType.RBD && volumeVO != null) {
|
||||
snapshotSvr.deleteSnapshot(snapshotOnPrimaryInfo);
|
||||
}
|
||||
snapshotOnPrimary.setState(State.Destroyed);
|
||||
snapshotStoreDao.update(snapshotOnPrimary.getId(), snapshotOnPrimary);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to delete snapshot: ", e);
|
||||
/**
|
||||
* Deletes the snapshot on secondary storage.
|
||||
* It can return false when the snapshot was stored on primary storage and not backed up on secondary; therefore, the snapshot should also be deleted on primary storage even when this method returns false.
|
||||
*/
|
||||
private boolean deleteSnapshotOnSecondaryStorage(Long snapshotId, SnapshotInfo snapshotOnImage, SnapshotObject obj) throws NoTransitionException {
|
||||
obj.processEvent(Snapshot.Event.DestroyRequested);
|
||||
List<VolumeDetailVO> volumesFromSnapshot;
|
||||
volumesFromSnapshot = _volumeDetailsDaoImpl.findDetails("SNAPSHOT_ID", String.valueOf(snapshotId), null);
|
||||
|
||||
if (volumesFromSnapshot.size() > 0) {
|
||||
try {
|
||||
obj.processEvent(Snapshot.Event.OperationFailed);
|
||||
} catch (NoTransitionException e1) {
|
||||
s_logger.debug("Failed to change snapshot state: " + e.toString());
|
||||
s_logger.debug("Failed to change snapshot state: " + e1.toString());
|
||||
}
|
||||
return false;
|
||||
throw new InvalidParameterValueException("Unable to perform delete operation, Snapshot with id: " + snapshotId + " is in use ");
|
||||
}
|
||||
|
||||
return true;
|
||||
boolean result = deleteSnapshotChain(snapshotOnImage);
|
||||
obj.processEvent(Snapshot.Event.OperationSucceeded);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the snapshot on primary storage. It returns true when the snapshot was not found on primary storage; </br>
|
||||
* In case of failure while deleting the snapshot, it will throw one of the following exceptions: CloudRuntimeException, InterruptedException, or ExecutionException. </br>
|
||||
*/
|
||||
private boolean deleteSnapshotOnPrimary(Long snapshotId, SnapshotInfo snapshotOnPrimaryInfo) {
|
||||
SnapshotDataStoreVO snapshotOnPrimary = snapshotStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
|
||||
if (isSnapshotOnPrimaryStorage(snapshotId)) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(String.format("Snapshot reference is found on primary storage for snapshot id: %d, performing snapshot deletion on primary", snapshotId));
|
||||
}
|
||||
if (snapshotSvr.deleteSnapshot(snapshotOnPrimaryInfo)) {
|
||||
snapshotOnPrimary.setState(State.Destroyed);
|
||||
snapshotStoreDao.update(snapshotOnPrimary.getId(), snapshotOnPrimary);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(String.format("Successfully deleted snapshot id: %d on primary storage", snapshotId));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(String.format("Snapshot reference is not found on primary storage for snapshot id: %d, skipping snapshot deletion on primary", snapshotId));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the snapshot volume is on primary storage.
|
||||
*/
|
||||
private boolean isSnapshotOnPrimaryStorage(long snapshotId) {
|
||||
SnapshotDataStoreVO snapshotOnPrimary = snapshotStoreDao.findBySnapshot(snapshotId, DataStoreRole.Primary);
|
||||
if (snapshotOnPrimary != null) {
|
||||
long volumeId = snapshotOnPrimary.getVolumeId();
|
||||
VolumeVO volumeVO = volumeDao.findById(volumeId);
|
||||
return volumeVO != null && volumeVO.getRemoved() == null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -27,8 +27,8 @@
|
||||
http://www.springframework.org/schema/context/spring-context.xsd"
|
||||
>
|
||||
|
||||
<bean id="xenserverSnapshotStrategy"
|
||||
class="org.apache.cloudstack.storage.snapshot.XenserverSnapshotStrategy" />
|
||||
<bean id="defaultSnapshotStrategy"
|
||||
class="org.apache.cloudstack.storage.snapshot.DefaultSnapshotStrategy" />
|
||||
|
||||
<bean id="storageSystemSnapshotStrategy"
|
||||
class="org.apache.cloudstack.storage.snapshot.StorageSystemSnapshotStrategy" />
|
||||
|
||||
@ -94,6 +94,7 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
|
||||
|
||||
protected List<StoragePool> reorderPoolsByCapacity(DeploymentPlan plan,
|
||||
List<StoragePool> pools) {
|
||||
Long zoneId = plan.getDataCenterId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
short capacityType;
|
||||
if(pools != null && pools.size() != 0){
|
||||
@ -102,7 +103,7 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Long> poolIdsByCapacity = capacityDao.orderHostsByFreeCapacity(clusterId, capacityType);
|
||||
List<Long> poolIdsByCapacity = capacityDao.orderHostsByFreeCapacity(zoneId, clusterId, capacityType);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("List of pools in descending order of free capacity: "+ poolIdsByCapacity);
|
||||
}
|
||||
|
||||
@ -29,6 +29,8 @@ import org.springframework.stereotype.Component;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
|
||||
import com.cloud.capacity.Capacity;
|
||||
import com.cloud.capacity.dao.CapacityDao;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
@ -43,6 +45,8 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
private static final Logger LOGGER = Logger.getLogger(ZoneWideStoragePoolAllocator.class);
|
||||
@Inject
|
||||
private DataStoreManager dataStoreMgr;
|
||||
@Inject
|
||||
private CapacityDao capacityDao;
|
||||
|
||||
|
||||
@Override
|
||||
@ -110,6 +114,40 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
|
||||
return !ScopeType.ZONE.equals(storagePoolVO.getScope()) || !storagePoolVO.isManaged();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<StoragePool> reorderPoolsByCapacity(DeploymentPlan plan,
|
||||
List<StoragePool> pools) {
|
||||
Long zoneId = plan.getDataCenterId();
|
||||
short capacityType;
|
||||
if(pools != null && pools.size() != 0){
|
||||
capacityType = pools.get(0).getPoolType().isShared() ? Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED : Capacity.CAPACITY_TYPE_LOCAL_STORAGE;
|
||||
} else{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Long> poolIdsByCapacity = capacityDao.orderHostsByFreeCapacity(zoneId, null, capacityType);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("List of zone-wide storage pools in descending order of free capacity: "+ poolIdsByCapacity);
|
||||
}
|
||||
|
||||
//now filter the given list of Pools by this ordered list
|
||||
Map<Long, StoragePool> poolMap = new HashMap<>();
|
||||
for (StoragePool pool : pools) {
|
||||
poolMap.put(pool.getId(), pool);
|
||||
}
|
||||
List<Long> matchingPoolIds = new ArrayList<>(poolMap.keySet());
|
||||
|
||||
poolIdsByCapacity.retainAll(matchingPoolIds);
|
||||
|
||||
List<StoragePool> reorderedPools = new ArrayList<>();
|
||||
for(Long id: poolIdsByCapacity){
|
||||
reorderedPools.add(poolMap.get(id));
|
||||
}
|
||||
|
||||
return reorderedPools;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<StoragePool> reorderPoolsByNumberOfVolumes(DeploymentPlan plan, List<StoragePool> pools, Account account) {
|
||||
if (account == null) {
|
||||
|
||||
@ -128,6 +128,14 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
private String _manageSnapshotPath;
|
||||
private int _cmdsTimeout;
|
||||
|
||||
private static final String MANAGE_SNAPSTHOT_CREATE_OPTION = "-c";
|
||||
private static final String MANAGE_SNAPSTHOT_DESTROY_OPTION = "-d";
|
||||
private static final String NAME_OPTION = "-n";
|
||||
private static final String CEPH_MON_HOST = "mon_host";
|
||||
private static final String CEPH_AUTH_KEY = "key";
|
||||
private static final String CEPH_CLIENT_MOUNT_TIMEOUT = "client_mount_timeout";
|
||||
private static final String CEPH_DEFAULT_MOUNT_TIMEOUT = "30";
|
||||
|
||||
public KVMStorageProcessor(final KVMStoragePoolManager storagePoolMgr, final LibvirtComputingResource resource) {
|
||||
this.storagePoolMgr = storagePoolMgr;
|
||||
this.resource = resource;
|
||||
@ -563,7 +571,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
final Script command = new Script(_createTmplPath, wait, s_logger);
|
||||
command.add("-f", disk.getPath());
|
||||
command.add("-t", tmpltPath);
|
||||
command.add("-n", templateName + ".qcow2");
|
||||
command.add(NAME_OPTION, templateName + ".qcow2");
|
||||
|
||||
final String result = command.execute();
|
||||
|
||||
@ -949,7 +957,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
} else {
|
||||
final Script command = new Script(_manageSnapshotPath, cmd.getWaitInMillSeconds(), s_logger);
|
||||
command.add("-b", snapshotDisk.getPath());
|
||||
command.add("-n", snapshotName);
|
||||
command.add(NAME_OPTION, snapshotName);
|
||||
command.add("-p", snapshotDestPath);
|
||||
if (isCreatedFromVmSnapshot) {
|
||||
descName = UUID.randomUUID().toString();
|
||||
@ -1010,14 +1018,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
}
|
||||
} else {
|
||||
if (primaryPool.getType() != StoragePoolType.RBD) {
|
||||
final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
|
||||
command.add("-d", snapshotDisk.getPath());
|
||||
command.add("-n", snapshotName);
|
||||
final String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.debug("Failed to delete snapshot on primary: " + result);
|
||||
// return new CopyCmdAnswer("Failed to backup snapshot: " + result);
|
||||
}
|
||||
deleteSnapshotViaManageSnapshotScript(snapshotName, snapshotDisk);
|
||||
}
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
@ -1035,6 +1036,16 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteSnapshotViaManageSnapshotScript(final String snapshotName, KVMPhysicalDisk snapshotDisk) {
|
||||
final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
|
||||
command.add(MANAGE_SNAPSTHOT_DESTROY_OPTION, snapshotDisk.getPath());
|
||||
command.add(NAME_OPTION, snapshotName);
|
||||
final String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.debug("Failed to delete snapshot on primary: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized String attachOrDetachISO(final Connect conn, final String vmName, String isoPath, final boolean isAttach) throws LibvirtException, URISyntaxException,
|
||||
InternalErrorException {
|
||||
String isoXml = null;
|
||||
@ -1494,12 +1505,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
*/
|
||||
if (primaryPool.getType() == StoragePoolType.RBD) {
|
||||
try {
|
||||
final Rados r = new Rados(primaryPool.getAuthUserName());
|
||||
r.confSet("mon_host", primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort());
|
||||
r.confSet("key", primaryPool.getAuthSecret());
|
||||
r.confSet("client_mount_timeout", "30");
|
||||
r.connect();
|
||||
s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
|
||||
Rados r = radosConnect(primaryPool);
|
||||
|
||||
final IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir());
|
||||
final Rbd rbd = new Rbd(io);
|
||||
@ -1516,8 +1522,8 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
} else {
|
||||
/* VM is not running, create a snapshot by ourself */
|
||||
final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
|
||||
command.add("-c", disk.getPath());
|
||||
command.add("-n", snapshotName);
|
||||
command.add(MANAGE_SNAPSTHOT_CREATE_OPTION, disk.getPath());
|
||||
command.add(NAME_OPTION, snapshotName);
|
||||
final String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.debug("Failed to manage snapshot: " + result);
|
||||
@ -1536,6 +1542,16 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private Rados radosConnect(final KVMStoragePool primaryPool) throws RadosException {
|
||||
Rados r = new Rados(primaryPool.getAuthUserName());
|
||||
r.confSet(CEPH_MON_HOST, primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort());
|
||||
r.confSet(CEPH_AUTH_KEY, primaryPool.getAuthSecret());
|
||||
r.confSet(CEPH_CLIENT_MOUNT_TIMEOUT, CEPH_DEFAULT_MOUNT_TIMEOUT);
|
||||
r.connect();
|
||||
s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet(CEPH_MON_HOST));
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer deleteVolume(final DeleteCommand cmd) {
|
||||
final VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
|
||||
@ -1624,12 +1640,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
String snapshotName = snapshotFullPath.substring(snapshotFullPath.lastIndexOf("/") + 1);
|
||||
snap_full_name = disk.getName() + "@" + snapshotName;
|
||||
if (primaryPool.getType() == StoragePoolType.RBD) {
|
||||
Rados r = new Rados(primaryPool.getAuthUserName());
|
||||
r.confSet("mon_host", primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort());
|
||||
r.confSet("key", primaryPool.getAuthSecret());
|
||||
r.confSet("client_mount_timeout", "30");
|
||||
r.connect();
|
||||
s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
|
||||
Rados r = radosConnect(primaryPool);
|
||||
IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir());
|
||||
Rbd rbd = new Rbd(io);
|
||||
RbdImage image = rbd.open(disk.getName());
|
||||
@ -1649,6 +1660,9 @@ public class KVMStorageProcessor implements StorageProcessor {
|
||||
rbd.close(image);
|
||||
r.ioCtxDestroy(io);
|
||||
}
|
||||
} else if (primaryPool.getType() == StoragePoolType.NetworkFilesystem) {
|
||||
s_logger.info(String.format("Attempting to remove snapshot (id=%s, name=%s, path=%s, storage type=%s) on primary storage", snapshotTO.getId(), snapshotTO.getName(), snapshotTO.getPath(), primaryPool.getType()));
|
||||
deleteSnapshotViaManageSnapshotScript(snapshotName, disk);
|
||||
} else {
|
||||
s_logger.warn("Operation not implemented for storage pool type of " + primaryPool.getType().toString());
|
||||
throw new InternalErrorException("Operation not implemented for storage pool type of " + primaryPool.getType().toString());
|
||||
|
||||
@ -371,6 +371,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
|
||||
// Reorder hosts in the decreasing order of free capacity.
|
||||
private List<? extends Host> reorderHostsByCapacity(DeploymentPlan plan, List<? extends Host> hosts) {
|
||||
Long zoneId = plan.getDataCenterId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
//Get capacity by which we should reorder
|
||||
String capacityTypeToOrder = _configDao.getValue(Config.HostCapacityTypeToOrderClusters.key());
|
||||
@ -378,7 +379,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
if("RAM".equalsIgnoreCase(capacityTypeToOrder)){
|
||||
capacityType = CapacityVO.CAPACITY_TYPE_MEMORY;
|
||||
}
|
||||
List<Long> hostIdsByFreeCapacity = _capacityDao.orderHostsByFreeCapacity(clusterId, capacityType);
|
||||
List<Long> hostIdsByFreeCapacity = _capacityDao.orderHostsByFreeCapacity(zoneId, clusterId, capacityType);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("List of hosts in descending order of free capacity in the cluster: "+ hostIdsByFreeCapacity);
|
||||
}
|
||||
|
||||
@ -3706,7 +3706,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
affinityGroups.addAll(listDomainLevelAffinityGroups(scDomain, searchFilter, domainId));
|
||||
}
|
||||
|
||||
return new Pair<List<AffinityGroupJoinVO>, Integer>(affinityGroups, uniqueGroupsPair.second());
|
||||
return new Pair<List<AffinityGroupJoinVO>, Integer>(affinityGroups, affinityGroups.size());
|
||||
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user