Skip to content

Commit

Permalink
Revert "server: fix attach uploaded volume (#10267)" (#10323)
Browse files Browse the repository at this point in the history
This reverts commit 1c84ce4.
  • Loading branch information
DaanHoogland authored Feb 6, 2025
1 parent df99a29 commit 802bf5f
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 330 deletions.
123 changes: 42 additions & 81 deletions server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,7 @@
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.Pod;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
Expand All @@ -155,7 +153,6 @@
import com.cloud.hypervisor.HypervisorCapabilitiesVO;
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
import com.cloud.offering.DiskOffering;
import com.cloud.org.Cluster;
import com.cloud.org.Grouping;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectManager;
Expand Down Expand Up @@ -326,8 +323,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
@Inject
private VmWorkJobDao _workJobDao;
@Inject
ClusterDao clusterDao;
@Inject
private ClusterDetailsDao _clusterDetailsDao;
@Inject
private StorageManager storageMgr;
Expand All @@ -351,8 +346,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
protected ProjectManager projectManager;
@Inject
protected StoragePoolDetailsDao storagePoolDetailsDao;
@Inject
HostPodDao podDao;


protected Gson _gson;
Expand Down Expand Up @@ -2387,18 +2380,25 @@ public Volume attachVolumeToVM(AttachVolumeCmd command) {
return attachVolumeToVM(command.getVirtualMachineId(), command.getId(), command.getDeviceId());
}

protected VolumeVO getVmExistingVolumeForVolumeAttach(UserVmVO vm, VolumeInfo volumeToAttach) {
private Volume orchestrateAttachVolumeToVM(Long vmId, Long volumeId, Long deviceId) {
VolumeInfo volumeToAttach = volFactory.getVolume(volumeId);

if (volumeToAttach.isAttachedVM()) {
throw new CloudRuntimeException("This volume is already attached to a VM.");
}

UserVmVO vm = _userVmDao.findById(vmId);
VolumeVO existingVolumeOfVm = null;
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
List<VolumeVO> rootVolumesOfVm = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT);
List<VolumeVO> rootVolumesOfVm = _volsDao.findByInstanceAndType(vmId, Volume.Type.ROOT);
if (rootVolumesOfVm.size() > 1 && template != null && !template.isDeployAsIs()) {
throw new CloudRuntimeException("The VM " + vm.getHostName() + " has more than one ROOT volume and is in an invalid state.");
} else {
if (!rootVolumesOfVm.isEmpty()) {
existingVolumeOfVm = rootVolumesOfVm.get(0);
} else {
// locate data volume of the vm
List<VolumeVO> diskVolumesOfVm = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.DATADISK);
List<VolumeVO> diskVolumesOfVm = _volsDao.findByInstanceAndType(vmId, Volume.Type.DATADISK);
for (VolumeVO diskVolume : diskVolumesOfVm) {
if (diskVolume.getState() != Volume.State.Allocated) {
existingVolumeOfVm = diskVolume;
Expand All @@ -2407,89 +2407,45 @@ protected VolumeVO getVmExistingVolumeForVolumeAttach(UserVmVO vm, VolumeInfo vo
}
}
}
if (existingVolumeOfVm == null) {
if (s_logger.isTraceEnabled()) {
s_logger.trace(String.format("No existing volume found for VM (%s/%s) to attach volume %s/%s",
if (s_logger.isTraceEnabled()) {
String msg = "attaching volume %s/%s to a VM (%s/%s) with an existing volume %s/%s on primary storage %s";
if (existingVolumeOfVm != null) {
s_logger.trace(String.format(msg,
volumeToAttach.getName(), volumeToAttach.getUuid(),
vm.getName(), vm.getUuid(),
volumeToAttach.getName(), volumeToAttach.getUuid()));
existingVolumeOfVm.getName(), existingVolumeOfVm.getUuid(),
existingVolumeOfVm.getPoolId()));
}
return null;
}
if (s_logger.isTraceEnabled()) {
String msg = "attaching volume %s/%s to a VM (%s/%s) with an existing volume %s/%s on primary storage %s";
s_logger.trace(String.format(msg,
volumeToAttach.getName(), volumeToAttach.getUuid(),
vm.getName(), vm.getUuid(),
existingVolumeOfVm.getName(), existingVolumeOfVm.getUuid(),
existingVolumeOfVm.getPoolId()));
}
return existingVolumeOfVm;
}

protected StoragePool getPoolForAllocatedOrUploadedVolumeForAttach(final VolumeInfo volumeToAttach, final UserVmVO vm) {
DataCenter zone = _dcDao.findById(vm.getDataCenterId());
Pair<Long, Long> clusterHostId = virtualMachineManager.findClusterAndHostIdForVm(vm, false);
long podId = vm.getPodIdToDeployIn();
if (clusterHostId.first() != null) {
Cluster cluster = clusterDao.findById(clusterHostId.first());
podId = cluster.getPodId();
}
Pod pod = podDao.findById(podId);
DiskOfferingVO offering = _diskOfferingDao.findById(volumeToAttach.getDiskOfferingId());
DiskProfile diskProfile = new DiskProfile(volumeToAttach.getId(), volumeToAttach.getVolumeType(),
volumeToAttach.getName(), volumeToAttach.getId(), volumeToAttach.getSize(), offering.getTagsArray(),
offering.isUseLocalStorage(), offering.isRecreatable(),
volumeToAttach.getTemplateId());
diskProfile.setHyperType(vm.getHypervisorType());
StoragePool pool = _volumeMgr.findStoragePool(diskProfile, zone, pod, clusterHostId.first(),
clusterHostId.second(), vm, Collections.emptySet());
if (pool == null) {
throw new CloudRuntimeException(String.format("Failed to find a primary storage for volume in state: %s", volumeToAttach.getState()));
}
return pool;
}

protected VolumeInfo createVolumeOnPrimaryForAttachIfNeeded(final VolumeInfo volumeToAttach, final UserVmVO vm, VolumeVO existingVolumeOfVm) {

HypervisorType rootDiskHyperType = vm.getHypervisorType();
HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());

VolumeInfo newVolumeOnPrimaryStorage = volumeToAttach;
boolean volumeOnSecondary = volumeToAttach.getState() == Volume.State.Uploaded;
if (!Arrays.asList(Volume.State.Allocated, Volume.State.Uploaded).contains(volumeToAttach.getState())) {
return newVolumeOnPrimaryStorage;
}

//don't create volume on primary storage if its being attached to the vm which Root's volume hasn't been created yet
StoragePool destPrimaryStorage = null;
StoragePoolVO destPrimaryStorage = null;
if (existingVolumeOfVm != null && !existingVolumeOfVm.getState().equals(Volume.State.Allocated)) {
destPrimaryStorage = _storagePoolDao.findById(existingVolumeOfVm.getPoolId());
if (s_logger.isTraceEnabled() && destPrimaryStorage != null) {
s_logger.trace(String.format("decided on target storage: %s/%s", destPrimaryStorage.getName(), destPrimaryStorage.getUuid()));
}
}
if (destPrimaryStorage == null) {
destPrimaryStorage = getPoolForAllocatedOrUploadedVolumeForAttach(volumeToAttach, vm);
}
try {
if (volumeOnSecondary && Storage.StoragePoolType.PowerFlex.equals(destPrimaryStorage.getPoolType())) {
throw new InvalidParameterValueException("Cannot attach uploaded volume, this operation is unsupported on storage pool type " + destPrimaryStorage.getPoolType());
}
newVolumeOnPrimaryStorage = _volumeMgr.createVolumeOnPrimaryStorage(vm, volumeToAttach,
vm.getHypervisorType(), destPrimaryStorage);
} catch (NoTransitionException e) {
s_logger.debug("Failed to create volume on primary storage", e);
throw new CloudRuntimeException("Failed to create volume on primary storage", e);
}
return newVolumeOnPrimaryStorage;
}

private Volume orchestrateAttachVolumeToVM(Long vmId, Long volumeId, Long deviceId) {
VolumeInfo volumeToAttach = volFactory.getVolume(volumeId);
boolean volumeOnSecondary = volumeToAttach.getState() == Volume.State.Uploaded;

if (volumeToAttach.isAttachedVM()) {
throw new CloudRuntimeException("This volume is already attached to a VM.");
if (destPrimaryStorage != null && (volumeToAttach.getState() == Volume.State.Allocated || volumeOnSecondary)) {
try {
if (volumeOnSecondary && destPrimaryStorage.getPoolType() == Storage.StoragePoolType.PowerFlex) {
throw new InvalidParameterValueException("Cannot attach uploaded volume, this operation is unsupported on storage pool type " + destPrimaryStorage.getPoolType());
}
newVolumeOnPrimaryStorage = _volumeMgr.createVolumeOnPrimaryStorage(vm, volumeToAttach, rootDiskHyperType, destPrimaryStorage);
} catch (NoTransitionException e) {
s_logger.debug("Failed to create volume on primary storage", e);
throw new CloudRuntimeException("Failed to create volume on primary storage", e);
}
}

UserVmVO vm = _userVmDao.findById(vmId);
VolumeVO existingVolumeOfVm = getVmExistingVolumeForVolumeAttach(vm, volumeToAttach);
VolumeInfo newVolumeOnPrimaryStorage = createVolumeOnPrimaryForAttachIfNeeded(volumeToAttach, vm, existingVolumeOfVm);

// reload the volume from db
newVolumeOnPrimaryStorage = volFactory.getVolume(newVolumeOnPrimaryStorage.getId());
boolean moveVolumeNeeded = needMoveVolume(existingVolumeOfVm, newVolumeOnPrimaryStorage);
Expand All @@ -2507,17 +2463,19 @@ private Volume orchestrateAttachVolumeToVM(Long vmId, Long volumeId, Long device
StoragePoolVO vmRootVolumePool = _storagePoolDao.findById(existingVolumeOfVm.getPoolId());

try {
HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());
newVolumeOnPrimaryStorage = _volumeMgr.moveVolume(newVolumeOnPrimaryStorage, vmRootVolumePool.getDataCenterId(), vmRootVolumePool.getPodId(), vmRootVolumePool.getClusterId(),
volumeToAttachHyperType);
} catch (ConcurrentOperationException | StorageUnavailableException e) {
} catch (ConcurrentOperationException e) {
s_logger.debug("move volume failed", e);
throw new CloudRuntimeException("move volume failed", e);
} catch (StorageUnavailableException e) {
s_logger.debug("move volume failed", e);
throw new CloudRuntimeException("move volume failed", e);
}
}
VolumeVO newVol = _volsDao.findById(newVolumeOnPrimaryStorage.getId());
// Getting the fresh vm object in case of volume migration to check the current state of VM
if (moveVolumeNeeded) {
if (moveVolumeNeeded || volumeOnSecondary) {
vm = _userVmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("VM not found.");
Expand Down Expand Up @@ -2701,6 +2659,9 @@ private void checkDeviceId(Long deviceId, VolumeInfo volumeToAttach, UserVmVO vm
if (!_volsDao.findByInstanceAndDeviceId(vm.getId(), 0).isEmpty()) {
throw new InvalidParameterValueException("Vm already has root volume attached to it");
}
if (volumeToAttach.getState() == Volume.State.Uploaded) {
throw new InvalidParameterValueException("No support for Root volume attach in state " + Volume.State.Uploaded);
}
}
}

Expand Down
Loading

0 comments on commit 802bf5f

Please sign in to comment.