refactor continue

This commit is contained in:
Edison Su 2012-08-21 18:50:59 -07:00
parent 62b5988c79
commit 5150aff356
15 changed files with 560 additions and 428 deletions

View File

@ -115,7 +115,6 @@ public abstract class BaseCmd {
public static AccountService _accountService;
public static UserVmService _userVmService;
public static ManagementService _mgr;
public static StoragePoolService _storageService;
public static ResourceService _resourceService;
public static NetworkService _networkService;
public static SecurityGroupService _securityGroupService;
@ -146,7 +145,6 @@ public abstract class BaseCmd {
_accountService = locator.getManager(AccountService.class);
_configService = locator.getManager(ConfigurationService.class);
_userVmService = locator.getManager(UserVmService.class);
_storageService = locator.getManager(StoragePoolService.class);
_resourceService = locator.getManager(ResourceService.class);
_networkService = locator.getManager(NetworkService.class);
_securityGroupService = locator.getManager(SecurityGroupService.class);

View File

@ -119,7 +119,7 @@ public class AttachVolumeCmd extends BaseAsyncCmd {
@Override
public void execute(){
UserContext.current().setEventDetails("Volume Id: "+getId()+" VmId: "+getVirtualMachineId());
Volume result = _userVmService.attachVolumeToVM(this);
Volume result = _storageEngine.attachVolumeToVM(this);
if (result != null) {
VolumeResponse response = _responseGenerator.createVolumeResponse(result);
response.setResponseName(getCommandName());

View File

@ -79,7 +79,7 @@ public class DeleteVolumeCmd extends BaseCmd {
@Override
public void execute() throws ConcurrentOperationException {
UserContext.current().setEventDetails("Volume Id: "+getId());
boolean result = _storageService.deleteVolume(id);
boolean result = _storageEngine.deleteVolume(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);

View File

@ -24,6 +24,11 @@ import java.util.Date;
*
*/
public interface DiskOffering {
public enum Type {
Disk,
Service
};
long getId();
String getUniqueName();
@ -49,4 +54,8 @@ public interface DiskOffering {
boolean isCustomized();
void setDiskSize(long diskSize);
Type getType();
boolean isRecreatable();
}

View File

@ -27,18 +27,16 @@ import com.cloud.api.commands.DeletePoolCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.UpdateStoragePoolCmd;
import com.cloud.api.commands.UploadVolumeCmd;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.volume.Volume;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.VMInstanceVO;
public interface StoragePoolService {
/**

View File

@ -2,11 +2,23 @@ package com.cloud.storage.volume;
import java.util.List;
import com.cloud.api.commands.AttachVolumeCmd;
import com.cloud.api.commands.CreateVolumeCmd;
import com.cloud.api.commands.DeleteVolumeCmd;
import com.cloud.api.commands.DetachVolumeCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.offering.DiskOffering;
import com.cloud.storage.pool.StoragePool;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface VolumeService {
/**
@ -56,4 +68,24 @@ public interface VolumeService {
Volume copyVolume(Long volumeId, Long destStoragePoolId);
List<? extends Volume> searchForVolumes(ListVolumesCmd cmd);
void allocateVolume(Long vmId, Pair<? extends DiskOffering, Long> rootDiskOffering,
List<Pair<DiskOffering, Long>> dataDiskOfferings,
Long templateId, Account owner);
void prepareForMigration(VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest);
void prepare(VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, boolean recreate) throws StorageUnavailableException,
InsufficientStorageCapacityException, ConcurrentOperationException;
Volume attachVolumeToVM(AttachVolumeCmd command);
boolean attachIsoToVm(long isoId, long vmId);
boolean detachIsoToVm(long vmId);
Volume detachVolumeFromVM(DetachVolumeCmd cmd);
boolean vmStorageMigration(VirtualMachineProfile<? extends VirtualMachine> vm, StoragePool destPool) throws ConcurrentOperationException;
boolean deleteVolume(DeleteVolumeCmd cmd);
void release(VirtualMachineProfile<? extends VirtualMachine> profile);
void cleanupVolumes(long vmId) throws ConcurrentOperationException;
void recreateVolume(long volumeId, long vmId) throws ConcurrentOperationException;
}

View File

@ -43,11 +43,6 @@ import com.cloud.utils.db.GenericDao;
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING, length=32)
public class DiskOfferingVO implements DiskOffering, Identity {
public enum Type {
Disk,
Service
};
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")

View File

@ -1,40 +0,0 @@
package com.cloud.storage.orchestra;
import java.util.List;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.api.commands.AttachVolumeCmd;
import com.cloud.api.commands.CreateVolumeCmd;
import com.cloud.capacity.CapacityVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.pool.StoragePool;
import com.cloud.storage.volume.Volume;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfileImpl;
public interface StorageOrchestraEngine {
void prepareForMigration(VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest);
void prepare(VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, boolean recreate) throws StorageUnavailableException,
InsufficientStorageCapacityException, ConcurrentOperationException;
void allocateVolume(Long vmId, Pair<? extends DiskOfferingVO, Long> rootDiskOffering,
List<Pair<DiskOfferingVO, Long>> dataDiskOfferings,
Long templateId, Account owner);
VolumeVO createVolume(CreateVolumeCmd cmd);
VolumeVO allocVolume(CreateVolumeCmd cmd)
throws ResourceAllocationException;
Volume attachVolumeToVM(AttachVolumeCmd command);
boolean attachIsoToVm(long isoId, long vmId);
boolean detachIsoToVm(long vmId);
}

View File

@ -1,5 +1,7 @@
hpackage com.cloud.storage.orchestra;
package com.cloud.storage.orchestra;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
@ -26,13 +28,36 @@ import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.api.BaseCmd;
import com.cloud.api.commands.AttachVolumeCmd;
import com.cloud.api.commands.CancelPrimaryStorageMaintenanceCmd;
import com.cloud.api.commands.CopyTemplateCmd;
import com.cloud.api.commands.CreateSnapshotPolicyCmd;
import com.cloud.api.commands.CreateStoragePoolCmd;
import com.cloud.api.commands.CreateVolumeCmd;
import com.cloud.api.commands.DeleteIsoCmd;
import com.cloud.api.commands.DeletePoolCmd;
import com.cloud.api.commands.DeleteSnapshotPoliciesCmd;
import com.cloud.api.commands.DeleteTemplateCmd;
import com.cloud.api.commands.DeleteVolumeCmd;
import com.cloud.api.commands.DetachVolumeCmd;
import com.cloud.api.commands.ExtractIsoCmd;
import com.cloud.api.commands.ExtractTemplateCmd;
import com.cloud.api.commands.ListRecurringSnapshotScheduleCmd;
import com.cloud.api.commands.ListSnapshotPoliciesCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
import com.cloud.api.commands.ListTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.api.commands.RegisterIsoCmd;
import com.cloud.api.commands.RegisterTemplateCmd;
import com.cloud.api.commands.UpdateStoragePoolCmd;
import com.cloud.api.commands.UpdateTemplateOrIsoPermissionsCmd;
import com.cloud.api.commands.UploadVolumeCmd;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobVO;
import com.cloud.async.BaseAsyncJobExecutor;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
@ -42,15 +67,22 @@ import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventVO;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientStorageCapacityException;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.DiskOffering;
import com.cloud.org.Grouping;
import com.cloud.resource.ResourceManager;
import com.cloud.service.ServiceOfferingVO;
@ -75,6 +107,8 @@ import com.cloud.storage.pool.Storage.TemplateType;
import com.cloud.storage.pool.StoragePoolManager;
import com.cloud.storage.snapshot.Snapshot;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.storage.snapshot.SnapshotPolicy;
import com.cloud.storage.snapshot.SnapshotSchedule;
import com.cloud.storage.volume.Volume;
import com.cloud.storage.volume.VolumeManagerImpl;
import com.cloud.storage.volume.Volume.Event;
@ -134,8 +168,8 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
protected UserVmDao _userVmDao;
@Inject
protected VMTemplateDao _templateDao;
@Inject
protected ConfigurationDao _configDao;
@Inject
protected StoragePoolManager _storagePoolMgr;
@ -373,8 +407,8 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
@Override
public void allocateVolume(Long vmId,
Pair<? extends DiskOfferingVO, Long> rootDiskOffering,
List<Pair<DiskOfferingVO, Long>> dataDiskOfferings, Long templateId, Account owner) {
Pair<? extends DiskOffering, Long> rootDiskOffering,
List<Pair<DiskOffering, Long>> dataDiskOfferings, Long templateId, Account owner) {
_volumeMgr.allocateVolume(vmId, rootDiskOffering, dataDiskOfferings, templateId, owner);
}
@ -399,41 +433,43 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
}
@Override
public void prepareForMigration(VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest) {
List<VolumeVO> vols = _volsDao.findUsableVolumesForInstance(vm.getId());
if (s_logger.isDebugEnabled()) {
s_logger.debug("Preparing " + vols.size() + " volumes for " + vm);
}
@Override
public void prepareForMigration(VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest) {
List<VolumeVO> vols = _volumeDao.findUsableVolumesForInstance(vm.getId());
if (s_logger.isDebugEnabled()) {
s_logger.debug("Preparing " + vols.size() + " volumes for " + vm);
}
for (VolumeVO vol : vols) {
StoragePool pool = _storagePoolDao.findById(vol.getPoolId());
vm.addDisk(new VolumeTO(vol, pool));
}
for (VolumeVO vol : vols) {
StoragePool pool = _storagePoolDao.findById(vol.getPoolId());
vm.addDisk(new VolumeTO(vol, pool));
}
if (vm.getType() == VirtualMachine.Type.User) {
UserVmVO userVM = (UserVmVO) vm.getVirtualMachine();
if (userVM.getIsoId() != null) {
Pair<String, String> isoPathPair = getAbsoluteIsoPath(userVM.getIsoId(), userVM.getDataCenterIdToDeployIn());
if (isoPathPair != null) {
String isoPath = isoPathPair.first();
VolumeTO iso = new VolumeTO(vm.getId(), Volume.Type.ISO, StoragePoolType.ISO, null, null, null, isoPath, 0, null, null);
vm.addDisk(iso);
}
}
}
}
if (vm.getType() == VirtualMachine.Type.User) {
UserVmVO userVM = (UserVmVO) vm.getVirtualMachine();
if (userVM.getIsoId() != null) {
long isoId = userVM.getIsoId();
VMTemplateVO iso = _templateDao.findById(isoId);
Map<String, String> isoPathPair = _templateMgr.getAbsoluteIsoPath(iso, userVM.getDataCenterIdToDeployIn());
if (!isoPathPair.isEmpty()) {
String isoPath = isoPathPair.get("isoPath");
VolumeTO isoTO = new VolumeTO(vm.getId(), Volume.Type.ISO, StoragePoolType.ISO, null, null, null, isoPath, 0, null, null);
vm.addDisk(isoTO);
}
}
}
}
@Override
public boolean configure(String name, Map<String, Object> params)
throws ConfigurationException {
String _customDiskOfferingMinSizeStr = configDao.getValue(Config.CustomDiskOfferingMinSize.toString());
String _customDiskOfferingMinSizeStr = _configDao.getValue(Config.CustomDiskOfferingMinSize.toString());
_customDiskOfferingMinSize = NumbersUtil.parseInt(_customDiskOfferingMinSizeStr, Integer.parseInt(Config.CustomDiskOfferingMinSize.getDefaultValue()));
String _customDiskOfferingMaxSizeStr = configDao.getValue(Config.CustomDiskOfferingMaxSize.toString());
String _customDiskOfferingMaxSizeStr = _configDao.getValue(Config.CustomDiskOfferingMaxSize.toString());
_customDiskOfferingMaxSize = NumbersUtil.parseInt(_customDiskOfferingMaxSizeStr, Integer.parseInt(Config.CustomDiskOfferingMaxSize.getDefaultValue()));
String maxVolumeSizeInGbString = configDao.getValue("storage.max.volume.size");
String maxVolumeSizeInGbString = _configDao.getValue("storage.max.volume.size");
_maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, 2000);
return true;
}
@ -456,12 +492,19 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
return null;
}
@Override
public void release(VirtualMachineProfile<? extends VirtualMachine> profile) {
List<VolumeTO> volumes = profile.getDisks();
for (VolumeTO volumeT : volumes) {
long volumeId = volumeT.getId();
VolumeVO volume = _volumeDao.findById(volumeId);
_volumeMgr.release(volume);
}
}
@Override
public boolean StorageMigration(VirtualMachineProfile<? extends VirtualMachine> vm, StoragePool destPool) throws ConcurrentOperationException {
public boolean vmStorageMigration(VirtualMachineProfile<? extends VirtualMachine> vm, StoragePool destPool) throws ConcurrentOperationException {
List<VolumeVO> vols = _volumeDao.findUsableVolumesForInstance(vm.getId());
List<Volume> volumesNeedToMigrate = new ArrayList<Volume>();
@ -484,7 +527,7 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
return true;
}
return migrateVolumes(volumesNeedToMigrate, destPool);
return _volumeMgr.migrateVolumes(volumesNeedToMigrate, destPool);
}
@ -512,7 +555,7 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
List<Volume> vols = new ArrayList<Volume>();
vols.add(vol);
migrateVolumes(vols, destPool);
_volumeMgr.migrateVolumes(vols, destPool);
return vol;
}
@ -534,7 +577,22 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
throw new InvalidParameterValueException("Please specify a valid User VM.");
}
_accountMgr.checkAccess(caller, null, true, volume, vm);
return _volumeMgr.attachVolumeToVM(volume, vm, deviceId);
try {
return _volumeMgr.attachVolumeToVM(volume, vm, deviceId);
} catch (StorageUnavailableException e) {
s_logger.debug("Failed to attache volume " + volume + ", due to " + e.toString());
return null;
} catch (AgentUnavailableException e) {
s_logger.debug("Failed to attache volume " + volume + ", due to " + e.toString());
return null;
} catch (ConcurrentOperationException e) {
s_logger.debug("Failed to attache volume " + volume + ", due to " + e.toString());
return null;
} catch (OperationTimedoutException e) {
s_logger.debug("Failed to attache volume " + volume + ", due to " + e.toString());
return null;
}
}
@ -542,7 +600,6 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
@ActionEvent(eventType = EventTypes.EVENT_ISO_ATTACH, eventDescription = "attaching ISO", async = true)
public boolean attachIsoToVm(long isoId, long vmId) {
Account caller = UserContext.current().getCaller();
Long userId = UserContext.current().getCallerUserId();
UserVmVO vm = _userVmDao.findById(vmId);
if (vm == null) {
@ -585,4 +642,257 @@ public class StorageOrchestraEngineImpl implements StorageOrchestraEngine, Manag
_volumeMgr.detachISOToVM(vm);
return true;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true)
public Volume detachVolumeFromVM(DetachVolumeCmd cmd) {
Account caller = UserContext.current().getCaller();
if ((cmd.getId() == null && cmd.getDeviceId() == null && cmd.getVirtualMachineId() == null) || (cmd.getId() != null && (cmd.getDeviceId() != null || cmd.getVirtualMachineId() != null))
|| (cmd.getId() == null && (cmd.getDeviceId() == null || cmd.getVirtualMachineId() == null))) {
throw new InvalidParameterValueException("Please provide either a volume id, or a tuple(device id, instance id)");
}
Long volumeId = cmd.getId();
VolumeVO volume = null;
if (volumeId != null) {
volume = _volumeDao.findById(volumeId);
} else {
volume = _volumeDao.findByInstanceAndDeviceId(cmd.getVirtualMachineId(), cmd.getDeviceId()).get(0);
}
if (volume == null) {
throw new InvalidParameterValueException("Unable to find volume with ID: " + volumeId);
}
_accountMgr.checkAccess(caller, null, true, volume);
Long vmId = null;
if (cmd.getVirtualMachineId() == null) {
vmId = volume.getInstanceId();
} else {
vmId = cmd.getVirtualMachineId();
}
UserVmVO vm = _userVmDao.findById(vmId);
return _volumeMgr.detachVolumeFromVM(volume, vm);
}
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DELETE, eventDescription = "deleting volume")
public boolean deleteVolume(DeleteVolumeCmd cmd) {
Long volumeId = cmd.getId();
Account caller = UserContext.current().getCaller();
VolumeVO volume = _volumeDao.findById(volumeId);
if (volume == null) {
throw new InvalidParameterValueException("Unable to find volume with ID: " + volumeId);
}
_accountMgr.checkAccess(caller, null, true, volume);
try {
return _volumeMgr.deleteVolume(volume);
} catch (ConcurrentOperationException e) {
s_logger.debug("Failed to delete volume " + volume + ", due to " + e.toString());
return false;
}
}
@Override
public StoragePool createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceUnavailableException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean deletePool(DeletePoolCmd cmd) {
// TODO Auto-generated method stub
return false;
}
@Override
public StoragePool prepareStorageForMaintenance(Long primaryStorageId) throws ResourceUnavailableException, InsufficientCapacityException {
// TODO Auto-generated method stub
return null;
}
@Override
public StoragePool cancelStorageForMaintenance(CancelPrimaryStorageMaintenanceCmd cmd) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return null;
}
@Override
public StoragePool updateStoragePool(UpdateStoragePoolCmd cmd) throws IllegalArgumentException {
// TODO Auto-generated method stub
return null;
}
@Override
public StoragePool getStoragePool(long id) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean deleteVolume(long volumeId) throws ConcurrentOperationException {
// TODO Auto-generated method stub
return false;
}
@Override
public Volume copyVolume(Long volumeId, Long destStoragePoolId) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<? extends Volume> searchForVolumes(ListVolumesCmd cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<? extends Snapshot> listSnapshots(ListSnapshotsCmd cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean deleteSnapshot(long snapshotId) {
// TODO Auto-generated method stub
return false;
}
@Override
public SnapshotPolicy createPolicy(CreateSnapshotPolicyCmd cmd, Account policyOwner) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<? extends SnapshotSchedule> findRecurringSnapshotSchedule(ListRecurringSnapshotScheduleCmd cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<? extends SnapshotPolicy> listPoliciesforVolume(ListSnapshotPoliciesCmd cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd) {
// TODO Auto-generated method stub
return false;
}
@Override
public Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException {
// TODO Auto-generated method stub
return null;
}
@Override
public Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId, Account snapshotOwner) {
// TODO Auto-generated method stub
return null;
}
@Override
public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException {
// TODO Auto-generated method stub
return null;
}
@Override
public VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws IllegalArgumentException, ResourceAllocationException {
// TODO Auto-generated method stub
return null;
}
@Override
public VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException {
// TODO Auto-generated method stub
return null;
}
@Override
public VirtualMachineTemplate prepareTemplate(long templateId, long zoneId) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean detachIso(long vmId) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean attachIso(long isoId, long vmId) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean deleteTemplate(DeleteTemplateCmd cmd) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean deleteIso(DeleteIsoCmd cmd) {
// TODO Auto-generated method stub
return false;
}
@Override
public Long extract(ExtractIsoCmd cmd) throws InternalErrorException {
// TODO Auto-generated method stub
return null;
}
@Override
public Long extract(ExtractTemplateCmd cmd) throws InternalErrorException {
// TODO Auto-generated method stub
return null;
}
@Override
public VirtualMachineTemplate getTemplate(long templateId) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<String> listTemplatePermissions(ListTemplateOrIsoPermissionsCmd cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean updateTemplateOrIsoPermissions(UpdateTemplateOrIsoPermissionsCmd cmd) {
// TODO Auto-generated method stub
return false;
}
@Override
public Volume uploadVolume(UploadVolumeCmd cmd) throws ResourceAllocationException {
// TODO Auto-generated method stub
return null;
}
@Override
public void cleanupVolumes(long vmId) throws ConcurrentOperationException {
_volumeMgr.cleanupVolumes(vmId);
}
@Override
public void recreateVolume(long volumeId, long vmId) throws ConcurrentOperationException {
VolumeVO volume = _volumeDao.findById(volumeId);
_volumeMgr.recreateVolume(volume, vmId);
}
}

View File

@ -1933,14 +1933,6 @@ public class StoragePoolManagerImpl implements StoragePoolManager, Manager, Clus
}
}
@Override
public void release(VirtualMachineProfile<? extends VMInstanceVO> profile) {
// add code here
}
protected class StorageGarbageCollector implements Runnable {
public StorageGarbageCollector() {

View File

@ -15,6 +15,7 @@ import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.DiskOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.StoragePoolVO;
@ -33,17 +34,6 @@ import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface VolumeManager {
/**
* Moves a volume from its current storage pool to a storage pool with enough capacity in the specified zone, pod, or cluster
* @param volume
* @param destPoolDcId
* @param destPoolPodId
* @param destPoolClusterId
* @return VolumeVO
* @throws ConcurrentOperationException
*/
VolumeVO moveVolume(VolumeVO volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, HypervisorType dataDiskHyperType) throws ConcurrentOperationException;
/**
* Create a volume based on the given criteria
* @param volume
@ -64,22 +54,6 @@ public interface VolumeManager {
VolumeVO createVolume(VolumeVO volume, long VMTemplateId, DiskOfferingVO diskOffering,
HypervisorType hyperType, StoragePool assignedPool) throws StorageUnavailableException, ConcurrentOperationException;
/**
* Marks the specified volume as destroyed in the management server database. The expunge thread will delete the volume from its storage pool.
* @param volume
* @return
*/
boolean destroyVolume(VolumeVO volume) throws ConcurrentOperationException;
/**
* Checks that one of the following is true:
* 1. The volume is not attached to any VM
* 2. The volume is attached to a VM that is running on a host with the KVM hypervisor, and the VM is stopped
* 3. The volume is attached to a VM that is running on a host with the XenServer hypervisor (the VM can be stopped or running)
* @return true if one of the above conditions is true
*/
boolean volumeInactive(VolumeVO volume);
/**
* Allocates one volume.
* @param <T>
@ -93,27 +67,16 @@ public interface VolumeManager {
* @return VolumeVO a persisted volume.
*/
DiskProfile allocateVolume(Long vmId,
Pair<? extends DiskOfferingVO, Long> rootDiskOffering,
List<Pair<DiskOfferingVO, Long>> dataDiskOfferings, Long templateId, Account owner);
Pair<? extends DiskOffering, Long> rootDiskOffering,
List<Pair<DiskOffering, Long>> dataDiskOfferings, Long templateId, Account owner);
void cleanupVolumes(long vmId) throws ConcurrentOperationException;
boolean processEvent(Volume vol, Event event)
throws NoTransitionException;
VolumeVO allocateDuplicateVolume(VolumeVO oldVol, Long templateId);
boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) throws ResourceAllocationException;
VolumeVO persistVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format);
/**
* Checks that the volume is stored on a shared storage pool
* @param volume
* @return true if the volume is on a shared storage pool, false otherwise
*/
boolean volumeOnSharedStoragePool(VolumeVO volume);
String getVmNameOnVolume(VolumeVO volume);
void expungeVolume(VolumeVO vol, boolean force);
Volume copyVolume(Long volumeId, Long destStoragePoolId);
@ -124,9 +87,17 @@ public interface VolumeManager {
Volume attachVolumeToVM(VolumeVO volume, UserVmVO vm, Long deviceId) throws StorageUnavailableException, ConcurrentOperationException, AgentUnavailableException, OperationTimedoutException;
boolean deleteVolume(long volumeId) throws ConcurrentOperationException;
void attachISOToVm(UserVmVO vm, VMTemplateVO iso);
void detachISOToVM(UserVmVO vm);
Volume detachVolumeFromVM(VolumeVO volume, UserVmVO vm);
boolean deleteVolume(VolumeVO volume) throws ConcurrentOperationException;
boolean migrateVolumes(List<Volume> volumes, StoragePool destPool) throws ConcurrentOperationException;
void release(VolumeVO volume);
void recreateVolume(VolumeVO volume, long vmId) throws ConcurrentOperationException;
}

View File

@ -32,6 +32,7 @@ import com.cloud.agent.api.to.VolumeTO;
import com.cloud.api.BaseCmd;
import com.cloud.api.commands.AttachVolumeCmd;
import com.cloud.api.commands.CreateVolumeCmd;
import com.cloud.api.commands.DetachVolumeCmd;
import com.cloud.api.commands.ListVolumesCmd;
import com.cloud.async.AsyncJobExecutor;
import com.cloud.async.AsyncJobVO;
@ -61,6 +62,7 @@ import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
import com.cloud.offering.DiskOffering;
import com.cloud.org.Grouping;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
import com.cloud.server.ResourceTag.TaggedResourceType;
@ -186,53 +188,8 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
@Inject
protected HypervisorCapabilitiesDao _hypervisorCapabilitiesDao;
@Override
@DB
public boolean destroyVolume(VolumeVO volume) throws ConcurrentOperationException {
try {
processEvent(volume, Volume.Event.DestroyRequested);
} catch (NoTransitionException e) {
throw new ConcurrentOperationException(e.toString());
}
long volumeId = volume.getId();
boolean success = false;
try {
_snapshotMgr.deletePoliciesForVolume(volumeId);
Long instanceId = volume.getInstanceId();
VMInstanceVO vmInstance = null;
if (instanceId != null) {
vmInstance = _vmInstanceDao.findById(instanceId);
}
processEvent(volume, Volume.Event.OperationSucceeded);
success = true;
if (instanceId == null || (vmInstance.getType().equals(VirtualMachine.Type.User))) {
// Decrement the resource count for volumes belonging user VM's
// only
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume);
// Log usage event for volumes belonging user VM's only
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName());
_usageEventDao.persist(usageEvent);
}
return success;
} catch (NoTransitionException e) {
throw new ConcurrentOperationException(e.toString());
} finally {
if (!success) {
try {
processEvent(volume, Volume.Event.OperationFailed);
} catch (NoTransitionException e) {
s_logger.debug("Failed to transit volume state: " + e.toString());
}
}
}
}
@Override
public VolumeVO allocateDuplicateVolume(VolumeVO oldVol, Long templateId) {
private VolumeVO allocateDuplicateVolume(VolumeVO oldVol, Long templateId) {
VolumeVO newVol = new VolumeVO(oldVol.getVolumeType(), oldVol.getName(), oldVol.getDataCenterId(), oldVol.getDomainId(), oldVol.getAccountId(), oldVol.getDiskOfferingId(), oldVol.getSize());
if (templateId != null) {
newVol.setTemplateId(templateId);
@ -447,6 +404,7 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
}
}
@Override
@DB
public boolean migrateVolumes(List<Volume> volumes, StoragePool destPool) throws ConcurrentOperationException {
Transaction txn = Transaction.currentTxn();
@ -585,8 +543,7 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
return true;
}
@Override
public boolean volumeInactive(VolumeVO volume) {
private boolean volumeInactive(VolumeVO volume) {
Long vmId = volume.getInstanceId();
if (vmId != null) {
UserVm vm = _userVmDao.findById(vmId);
@ -600,23 +557,21 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
}
return false;
}
private String getVmNameOnVolume(VolumeVO volume) {
Long vmId = volume.getInstanceId();
if (vmId != null) {
VMInstanceVO vm = _vmInstanceDao.findById(vmId);
@Override
public String getVmNameOnVolume(VolumeVO volume) {
Long vmId = volume.getInstanceId();
if (vmId != null) {
VMInstanceVO vm = _vmInstanceDao.findById(vmId);
if (vm == null) {
return null;
}
return vm.getInstanceName();
}
return null;
}
if (vm == null) {
return null;
}
return vm.getInstanceName();
}
return null;
}
@Override
public boolean volumeOnSharedStoragePool(VolumeVO volume) {
private boolean volumeOnSharedStoragePool(VolumeVO volume) {
boolean result = false;
if (volume.getState() != Volume.State.Ready) {
// if it's not ready, we don't care
@ -647,32 +602,6 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
return UUID.randomUUID().toString();
}
@Override
public VolumeVO moveVolume(VolumeVO volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, HypervisorType dataDiskHyperType) throws ConcurrentOperationException {
// Find a destination storage pool with the specified criteria
DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
DiskProfile dskCh = new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), diskOffering.getId(), diskOffering.getDiskSize(), diskOffering.getTagsArray(),
diskOffering.getUseLocalStorage(), diskOffering.isRecreatable(), null);
dskCh.setHyperType(dataDiskHyperType);
DataCenterVO destPoolDataCenter = _dcDao.findById(destPoolDcId);
HostPodVO destPoolPod = _podDao.findById(destPoolPodId);
StoragePoolVO destPool = _storagePoolMgr.findStoragePool(dskCh, destPoolDataCenter, destPoolPod, destPoolClusterId, null, new HashSet<StoragePool>());
String secondaryStorageURL = _storagePoolMgr.getSecondaryStorageURL(volume.getDataCenterId());
if (destPool == null) {
throw new CloudRuntimeException("Failed to find a storage pool with enough capacity to move the volume to.");
}
if (secondaryStorageURL == null) {
throw new CloudRuntimeException("Failed to find secondary storage.");
}
List<Volume> vols = new ArrayList<Volume>();
vols.add(volume);
migrateVolumes(vols, destPool);
return _volumeDao.findById(volume.getId());
}
public boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) throws ResourceAllocationException {
// permission check
@ -792,24 +721,15 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DELETE, eventDescription = "deleting volume")
public boolean deleteVolume(long volumeId) throws ConcurrentOperationException {
Account caller = UserContext.current().getCaller();
VolumeVO volume = _volumeDao.findById(volumeId);
if (volume == null) {
throw new InvalidParameterValueException("Unable to aquire volume with ID: " + volumeId);
public boolean deleteVolume(VolumeVO volume) throws ConcurrentOperationException {
if (volume.getInstanceId() != null) {
throw new InvalidParameterValueException("Please detach the volume at first, then delete it.");
}
if (!_snapshotMgr.canOperateOnVolume(volume)) {
throw new InvalidParameterValueException("There are snapshot creating on it, Unable to delete the volume");
}
_accountMgr.checkAccess(caller, null, true, volume);
if (volume.getInstanceId() != null) {
throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
}
if (volume.getState() == Volume.State.UploadOp) {
VolumeHostVO volumeHost = _volumeHostDao.findByVolumeId(volume.getId());
if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) {
@ -817,18 +737,28 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
}
}
if (volume.getState() != Volume.State.Destroy) {
destroyVolume(volume);
}
if (!Volume.State.Destroy.equals(volume.getState())) {
try {
processEvent(volume, Volume.Event.DestroyRequested);
try {
expungeVolume(volume, false);
} catch (Exception e) {
s_logger.warn("Failed to expunge volume:", e);
return false;
}
_snapshotMgr.deletePoliciesForVolume(volume.getId());
Long instanceId = volume.getInstanceId();
VMInstanceVO vmInstance = null;
if (instanceId != null) {
vmInstance = _vmInstanceDao.findById(instanceId);
}
return true;
if (instanceId == null || (vmInstance.getType().equals(VirtualMachine.Type.User))) {
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume);
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName());
_usageEventDao.persist(usageEvent);
}
} catch (NoTransitionException e) {
throw new ConcurrentOperationException(e.toString());
}
}
return expungeVolume(volume, false);
}
@Override
@ -853,13 +783,13 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
return volume;
}
private DiskProfile toDiskProfile(VolumeVO vol, DiskOfferingVO offering) {
private DiskProfile toDiskProfile(VolumeVO vol, DiskOffering offering) {
return new DiskProfile(vol.getId(), vol.getVolumeType(), vol.getName(), offering.getId(), vol.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.isRecreatable(),
vol.getTemplateId());
}
@Override
public DiskProfile allocateVolume(Long vmId, Pair<? extends DiskOfferingVO, Long> rootDiskOffering, List<Pair<DiskOfferingVO, Long>> dataDiskOfferings, Long templateId, Account owner) {
public DiskProfile allocateVolume(Long vmId, Pair<? extends DiskOffering, Long> rootDiskOffering, List<Pair<DiskOffering, Long>> dataDiskOfferings, Long templateId, Account owner) {
VirtualMachineTemplate template = _templateMgr.getTemplate(templateId);
VirtualMachine vm = _vmDao.findById(vmId);
DiskProfile diskProfile = null;
@ -871,13 +801,13 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
diskProfile = allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner);
}
for (Pair<DiskOfferingVO, Long> offering : dataDiskOfferings) {
for (Pair<DiskOffering, Long> offering : dataDiskOfferings) {
diskProfile = allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
}
return diskProfile;
}
public DiskProfile allocateRawVolume(Type type, String name, DiskOfferingVO offering, Long size, VirtualMachine vm, Account owner) {
public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, VirtualMachine vm, Account owner) {
if (size == null) {
size = offering.getDiskSize();
} else {
@ -907,7 +837,7 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
return toDiskProfile(vol, offering);
}
public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOfferingVO offering, VirtualMachineTemplate template, VirtualMachine vm, Account owner) {
public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offering, VirtualMachineTemplate template, VirtualMachine vm, Account owner) {
assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template really....";
SearchCriteria<VMTemplateHostVO> sc = HostTemplateStatesSearch.create();
@ -997,27 +927,39 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
s_logger.debug("Failed to delete " + volumeHost + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()));
return;
}
_volHostDao.remove(volumeHost.getId());
} else if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) {
s_logger.debug("Volume: " + vol.getName() + " is currently being uploaded; cant' delete it.");
throw new CloudRuntimeException("Please specify a volume that is not currently being uploaded.");
}
_volHostDao.remove(volumeHost.getId());
_volumeDao.remove(vol.getId());
return;
}
}
private boolean destroyVolumeOnBackend(VolumeVO volume, StoragePool pool, String vmName) throws StorageUnavailableException {
boolean removeVolume = false;
deleteVolumeFromSec(volume);
DestroyCommand cmd = new DestroyCommand(pool, volume, vmName);
Answer answer = _storagePoolMgr.sendToPool(pool, cmd);
if (answer != null && answer.getResult()) {
removeVolume = true;
} else if (answer != null && !answer.getResult()){
throw new CloudRuntimeException(answer.getDetails());
}
return removeVolume;
}
public void expungeVolume(VolumeVO vol, boolean force) {
@DB
protected boolean expungeVolume(VolumeVO vol, boolean force) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Expunging " + vol);
}
if (!Volume.State.Destroy.equals(vol.getState())) {
return;
return false;
}
deleteVolumeFromSec(vol);
String vmName = null;
if (vol.getVolumeType() == Type.ROOT && vol.getInstanceId() != null) {
VirtualMachine vm = _vmInstanceDao.findByIdIncludingRemoved(vol.getInstanceId());
@ -1033,29 +975,23 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
s_logger.debug("Marking volume that was never created as destroyed: " + vol);
}
_volumeDao.remove(vol.getId());
return;
return true;
}
StoragePoolVO pool = (StoragePoolVO) _storagePoolMgr.getStoragePool(poolId);
if (pool == null) {
s_logger.debug("Removing volume as storage pool is gone: " + poolId);
_volumeDao.remove(vol.getId());
return;
return true;
}
DestroyCommand cmd = new DestroyCommand(pool, vol, vmName);
boolean removeVolume = false;
try {
Answer answer = _storagePoolMgr.sendToPool(pool, cmd);
if (answer != null && answer.getResult()) {
removeVolume = true;
} else if (answer != null && !answer.getResult()){
s_logger.info("Failed to destroy volume " + vol + " from " + poolId + ", due to " + answer.getDetails());
}
removeVolume = destroyVolumeOnBackend(vol, pool, vmName);
} catch (StorageUnavailableException e) {
s_logger.info("Storage is unavailable currently. Will retry delete of " + vol + " from " + poolId);
} catch (RuntimeException ex) {
s_logger.info("Failed to expunge volume, but marking volume id=" + vol.getId() + " as expunged anyway " + "due to force=true. Volume failed to expunge due to ", ex);
s_logger.info("Failed to expunge volume, but marking volume id=" + vol.getId() + ", due to ", ex);
} finally {
if (removeVolume || force) {
if (force) {
@ -1063,11 +999,14 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
}
_volumeDao.remove(vol.getId());
removeVolume = true;
if (s_logger.isDebugEnabled()) {
s_logger.debug("Volume successfully expunged from " + poolId);
}
}
}
return removeVolume;
}
@Override
@ -1078,15 +1017,9 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
}
List<VolumeVO> volumesForVm = _volumeDao.findByInstance(vmId);
List<VolumeVO> toBeExpunged = new ArrayList<VolumeVO>();
Transaction txn = Transaction.currentTxn();
txn.start();
for (VolumeVO vol : volumesForVm) {
if (vol.getVolumeType().equals(Type.ROOT)) {
// This check is for VM in Error state (volume is already
// destroyed)
if (!vol.getState().equals(Volume.State.Destroy)) {
destroyVolume(vol);
}
toBeExpunged.add(vol);
} else {
if (s_logger.isDebugEnabled()) {
@ -1095,10 +1028,9 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
_volumeDao.detachVolume(vol.getId());
}
}
txn.commit();
for (VolumeVO expunge : toBeExpunged) {
expungeVolume(expunge, false);
deleteVolume(expunge);
}
}
@ -1548,4 +1480,55 @@ public class VolumeManagerImpl implements VolumeManager, Manager {
}
}
}
@Override
public Volume detachVolumeFromVM(VolumeVO volume, UserVmVO vm) {
if (volume.getVolumeType() != Volume.Type.DATADISK) {
throw new InvalidParameterValueException("Please specify a data volume.");
}
if (vm.getState() != State.Running && vm.getState() != State.Stopped && vm.getState() != State.Destroyed) {
throw new InvalidParameterValueException("Please specify a VM that is either running or stopped.");
}
boolean sendCommand = (vm.getState() == State.Running);
boolean success = false;
try {
if (sendCommand) {
Answer answer = null;
AttachVolumeCommand cmd = new AttachVolumeCommand(false, vm.getInstanceName(), volume.getPoolType(), volume.getFolder(), volume.getPath(), volume.getName(),
volume.getDeviceId(), volume.getChainInfo());
StoragePoolVO volumePool = _storagePoolDao.findById(volume.getPoolId());
cmd.setPoolUuid(volumePool.getUuid());
answer = _agentMgr.send(vm.getHostId(), cmd);
success = (answer != null && answer.getResult()) ? true : false;
} else {
success = true;
}
if (success) {
_volumeDao.detachVolume(volume.getId());
}
return _volumeDao.findById(volume.getId());
} catch (AgentUnavailableException e) {
throw new CloudRuntimeException(e.toString());
} catch (OperationTimedoutException e) {
throw new CloudRuntimeException(e.toString());
}
}
@Override
public void release(VolumeVO volume) {
}
@Override
public void recreateVolume(VolumeVO volume, long vmId) throws ConcurrentOperationException {
VolumeVO newVol = allocateDuplicateVolume(volume, null);
_volumeDao.attachVolume(newVol.getId(), vmId, newVol.getDeviceId());
_volumeDao.detachVolume(volume.getId());
deleteVolume(volume);
}
}

View File

@ -139,6 +139,7 @@ import com.cloud.network.security.SecurityGroup;
import com.cloud.network.security.SecurityGroupManager;
import com.cloud.network.security.dao.SecurityGroupDao;
import com.cloud.network.security.dao.SecurityGroupVMMapDao;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Availability;
import com.cloud.offering.ServiceOffering;
@ -174,6 +175,7 @@ import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeHostDao;
import com.cloud.storage.orchestra.StorageOrchestraEngine;
import com.cloud.storage.pool.Storage;
import com.cloud.storage.pool.StoragePool;
import com.cloud.storage.pool.StoragePoolManager;
@ -352,6 +354,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
protected VolumeHostDao _volumeHostDao;
@Inject
ResourceTagDao _resourceTagDao;
@Inject
StorageOrchestraEngine _storageEngine;
protected ScheduledExecutorService _executor = null;
@ -509,112 +513,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true)
public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) {
Account caller = UserContext.current().getCaller();
if ((cmmd.getId() == null && cmmd.getDeviceId() == null && cmmd.getVirtualMachineId() == null) || (cmmd.getId() != null && (cmmd.getDeviceId() != null || cmmd.getVirtualMachineId() != null))
|| (cmmd.getId() == null && (cmmd.getDeviceId() == null || cmmd.getVirtualMachineId() == null))) {
throw new InvalidParameterValueException("Please provide either a volume id, or a tuple(device id, instance id)");
}
Long volumeId = cmmd.getId();
VolumeVO volume = null;
if (volumeId != null) {
volume = _volsDao.findById(volumeId);
} else {
volume = _volsDao.findByInstanceAndDeviceId(cmmd.getVirtualMachineId(), cmmd.getDeviceId()).get(0);
}
Long vmId = null;
if (cmmd.getVirtualMachineId() == null) {
vmId = volume.getInstanceId();
} else {
vmId = cmmd.getVirtualMachineId();
}
// Check that the volume ID is valid
if (volume == null) {
throw new InvalidParameterValueException("Unable to find volume with ID: " + volumeId);
}
// Permissions check
_accountMgr.checkAccess(caller, null, true, volume);
// Check that the volume is a data volume
if (volume.getVolumeType() != Volume.Type.DATADISK) {
throw new InvalidParameterValueException("Please specify a data volume.");
}
// Check that the volume is currently attached to a VM
if (vmId == null) {
throw new InvalidParameterValueException("The specified volume is not attached to a VM.");
}
// Check that the volume is stored on shared storage
if (volume.getState() != Volume.State.Allocated && !_storageMgr.volumeOnSharedStoragePool(volume)) {
throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
}
// Check that the VM is in the correct state
UserVmVO vm = _vmDao.findById(vmId);
if (vm.getState() != State.Running && vm.getState() != State.Stopped && vm.getState() != State.Destroyed) {
throw new InvalidParameterValueException("Please specify a VM that is either running or stopped.");
}
AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
if (asyncExecutor != null) {
AsyncJobVO job = asyncExecutor.getJob();
if (s_logger.isInfoEnabled()) {
s_logger.info("Trying to attaching volume " + volumeId + "to vm instance:" + vm.getId() + ", update async job-" + job.getId() + " progress status");
}
_asyncMgr.updateAsyncJobAttachment(job.getId(), "volume", volumeId);
_asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, volumeId);
}
String errorMsg = "Failed to detach volume: " + volume.getName() + " from VM: " + vm.getHostName();
boolean sendCommand = (vm.getState() == State.Running);
Answer answer = null;
if (sendCommand) {
AttachVolumeCommand cmd = new AttachVolumeCommand(false, vm.getInstanceName(), volume.getPoolType(), volume.getFolder(), volume.getPath(), volume.getName(),
cmmd.getDeviceId() != null ? cmmd.getDeviceId() : volume.getDeviceId(), volume.getChainInfo());
StoragePoolVO volumePool = _storagePoolDao.findById(volume.getPoolId());
cmd.setPoolUuid(volumePool.getUuid());
try {
answer = _agentMgr.send(vm.getHostId(), cmd);
} catch (Exception e) {
throw new CloudRuntimeException(errorMsg + " due to: " + e.getMessage());
}
}
if (!sendCommand || (answer != null && answer.getResult())) {
// Mark the volume as detached
_volsDao.detachVolume(volume.getId());
if (answer != null && answer instanceof AttachVolumeAnswer) {
volume.setChainInfo(((AttachVolumeAnswer) answer).getChainInfo());
_volsDao.update(volume.getId(), volume);
}
return _volsDao.findById(volumeId);
} else {
if (answer != null) {
String details = answer.getDetails();
if (details != null && !details.isEmpty()) {
errorMsg += "; " + details;
}
}
throw new CloudRuntimeException(errorMsg);
}
}
@ -1352,18 +1251,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
} catch (NoTransitionException e1) {
s_logger.warn(e1.getMessage());
}
// destroy associated volumes for vm in error state
// get all volumes in non destroyed state
List<VolumeVO> volumesForThisVm = _volsDao.findUsableVolumesForInstance(vm.getId());
for (VolumeVO volume : volumesForThisVm) {
try {
if (volume.getState() != Volume.State.Destroy) {
_storageMgr.destroyVolume(volume);
}
} catch (ConcurrentOperationException e) {
s_logger.warn("Unable to delete volume:" + volume.getId() + " for vm:" + vmId + " whilst transitioning to error state");
}
}
String msg = "Failed to deploy Vm with Id: " + vmId;
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), msg, msg);
@ -1995,8 +1882,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
// If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
// Else, a disk offering is optional, and if present will be used to create the data disk
Pair<DiskOfferingVO, Long> rootDiskOffering = new Pair<DiskOfferingVO, Long>(null, null);
List<Pair<DiskOfferingVO, Long>> dataDiskOfferings = new ArrayList<Pair<DiskOfferingVO, Long>>();
Pair<DiskOffering, Long> rootDiskOffering = new Pair<DiskOffering, Long>(null, null);
List<Pair<DiskOffering, Long>> dataDiskOfferings = new ArrayList<Pair<DiskOffering, Long>>();
if (isIso) {
if (diskOfferingId == null) {
@ -2029,7 +1916,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
throw new InvalidParameterValueException("Disk offering " + diskOffering + " requires size parameter.");
}
}
dataDiskOfferings.add(new Pair<DiskOfferingVO, Long>(diskOffering, size));
dataDiskOfferings.add(new Pair<DiskOffering, Long>(diskOffering, size));
}
}
@ -3367,18 +3254,13 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
throw ex;
}
}
/* allocate a new volume from original template*/
VolumeVO newVol = _storageMgr.allocateDuplicateVolume(root, null);
_volsDao.attachVolume(newVol.getId(), vmId, newVol.getDeviceId());
/* Detach and destory the old root volume */
try {
_volsDao.detachVolume(root.getId());
_storageMgr.destroyVolume(root);
} catch (ConcurrentOperationException e) {
s_logger.debug("Unable to delete old root volume " + root.getId() + ", user may manually delete it", e);
}
_storageEngine.recreateVolume(root.getId(), vmId);
} catch (ConcurrentOperationException e) {
s_logger.debug("Failed to recreate volume: " + root.getId() + ", due to " + e.toString());
throw new CloudRuntimeException("Failed to recreate volume: " + root.getId() + ", due to " + e.toString());
}
if (needRestart) {
try {

View File

@ -35,6 +35,7 @@ import com.cloud.exception.VirtualMachineMigrationException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.NetworkVO;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.DiskOfferingVO;
@ -54,8 +55,8 @@ public interface VirtualMachineManager extends Manager {
<T extends VMInstanceVO> T allocate(T vm,
VMTemplateVO template,
ServiceOfferingVO serviceOffering,
Pair<? extends DiskOfferingVO, Long> rootDiskOffering,
List<Pair<DiskOfferingVO, Long>> dataDiskOfferings,
Pair<? extends DiskOffering, Long> rootDiskOffering,
List<Pair<DiskOffering, Long>> dataDiskOfferings,
List<Pair<NetworkVO, NicProfile>> networks,
Map<VirtualMachineProfile.Param, Object> params,
DeploymentPlan plan,
@ -66,7 +67,7 @@ public interface VirtualMachineManager extends Manager {
VMTemplateVO template,
ServiceOfferingVO serviceOffering,
Long rootSize,
Pair<DiskOfferingVO, Long> dataDiskOffering,
Pair<DiskOffering, Long> dataDiskOffering,
List<Pair<NetworkVO, NicProfile>> networks,
DeploymentPlan plan,
HypervisorType hyperType,

View File

@ -111,6 +111,7 @@ import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.resource.ResourceManager;
@ -167,7 +168,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
String _name;
@Inject
protected StoragePoolManager _storageMgr;
protected StorageOrchestraEngine _storageMgr;
@Inject
protected NetworkManager _networkMgr;
@Inject
@ -265,8 +266,8 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
@Override
@DB
public <T extends VMInstanceVO> T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Pair<? extends DiskOfferingVO, Long> rootDiskOffering,
List<Pair<DiskOfferingVO, Long>> dataDiskOfferings, List<Pair<NetworkVO, NicProfile>> networks, Map<VirtualMachineProfile.Param, Object> params, DeploymentPlan plan,
public <T extends VMInstanceVO> T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Pair<? extends DiskOffering, Long> rootDiskOffering,
List<Pair<DiskOffering, Long>> dataDiskOfferings, List<Pair<NetworkVO, NicProfile>> networks, Map<VirtualMachineProfile.Param, Object> params, DeploymentPlan plan,
HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Allocating entries for VM: " + vm);
@ -298,7 +299,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
if (dataDiskOfferings == null) {
dataDiskOfferings = new ArrayList<Pair<DiskOfferingVO, Long>>(0);
dataDiskOfferings = new ArrayList<Pair<DiskOffering, Long>>(0);
}
if (s_logger.isDebugEnabled()) {
@ -316,13 +317,13 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
@Override
public <T extends VMInstanceVO> T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Long rootSize, Pair<DiskOfferingVO, Long> dataDiskOffering,
public <T extends VMInstanceVO> T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Long rootSize, Pair<DiskOffering, Long> dataDiskOffering,
List<Pair<NetworkVO, NicProfile>> networks, DeploymentPlan plan, HypervisorType hyperType, Account owner) throws InsufficientCapacityException {
List<Pair<DiskOfferingVO, Long>> diskOfferings = new ArrayList<Pair<DiskOfferingVO, Long>>(1);
List<Pair<DiskOffering, Long>> diskOfferings = new ArrayList<Pair<DiskOffering, Long>>(1);
if (dataDiskOffering != null) {
diskOfferings.add(dataDiskOffering);
}
return allocate(vm, template, serviceOffering, new Pair<DiskOfferingVO, Long>(serviceOffering, rootSize), diskOfferings, networks, null, plan, hyperType, owner);
return allocate(vm, template, serviceOffering, new Pair<DiskOffering, Long>(serviceOffering, rootSize), diskOfferings, networks, null, plan, hyperType, owner);
}
@Override
@ -1223,7 +1224,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
boolean migrationResult = false;
try {
migrationResult = _storageMgr.StorageMigration(profile, destPool);
migrationResult = _storageMgr.vmStorageMigration(profile, destPool);
if (migrationResult) {
//if the vm is migrated to different pod in basic mode, need to reallocate ip