Return-Path: X-Original-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A6FC4D6FA for ; Wed, 22 Aug 2012 01:52:04 +0000 (UTC) Received: (qmail 27164 invoked by uid 500); 22 Aug 2012 01:52:04 -0000 Delivered-To: apmail-incubator-cloudstack-commits-archive@incubator.apache.org Received: (qmail 27135 invoked by uid 500); 22 Aug 2012 01:52:04 -0000 Mailing-List: contact cloudstack-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: cloudstack-dev@incubator.apache.org Delivered-To: mailing list cloudstack-commits@incubator.apache.org Received: (qmail 27124 invoked by uid 99); 22 Aug 2012 01:52:03 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 22 Aug 2012 01:52:03 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 85EDC1EC89; Wed, 22 Aug 2012 01:52:03 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: edison@apache.org To: cloudstack-commits@incubator.apache.org X-Mailer: ASF-Git Admin Mailer Subject: git commit: refactor continue Message-Id: <20120822015203.85EDC1EC89@tyr.zones.apache.org> Date: Wed, 22 Aug 2012 01:52:03 +0000 (UTC) Updated Branches: refs/heads/storagerefactor 62b5988c7 -> 5150aff35 refactor continue Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/5150aff3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/5150aff3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/5150aff3 Branch: refs/heads/storagerefactor Commit: 5150aff35609900a0dc7a3fc46cca6a7ea0ec959 Parents: 62b5988 Author: Edison Su Authored: Tue Aug 21 18:50:59 2012 -0700 Committer: Edison Su Committed: Tue Aug 21 18:50:59 2012 -0700 ---------------------------------------------------------------------- api/src/com/cloud/api/BaseCmd.java | 2 - .../com/cloud/api/commands/AttachVolumeCmd.java | 2 +- .../com/cloud/api/commands/DeleteVolumeCmd.java | 2 +- api/src/com/cloud/offering/DiskOffering.java | 9 + .../com/cloud/storage/pool/StoragePoolService.java | 6 +- .../com/cloud/storage/volume/VolumeService.java | 32 ++ core/src/com/cloud/storage/DiskOfferingVO.java | 5 - .../storage/orchestra/StorageOrchestraEngine.java | 40 -- .../orchestra/StorageOrchestraEngineImpl.java | 388 +++++++++++++-- .../cloud/storage/pool/StoragePoolManagerImpl.java | 8 - .../com/cloud/storage/volume/VolumeManager.java | 55 +-- .../cloud/storage/volume/VolumeManagerImpl.java | 277 +++++------ server/src/com/cloud/vm/UserVmManagerImpl.java | 146 +----- server/src/com/cloud/vm/VirtualMachineManager.java | 7 +- .../com/cloud/vm/VirtualMachineManagerImpl.java | 17 +- 15 files changed, 564 insertions(+), 432 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/api/src/com/cloud/api/BaseCmd.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/api/BaseCmd.java b/api/src/com/cloud/api/BaseCmd.java index a3ad4a6..ab78bc3 100755 --- a/api/src/com/cloud/api/BaseCmd.java +++ b/api/src/com/cloud/api/BaseCmd.java @@ -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); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/api/src/com/cloud/api/commands/AttachVolumeCmd.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/api/commands/AttachVolumeCmd.java b/api/src/com/cloud/api/commands/AttachVolumeCmd.java index 2566014..35383db 100755 --- a/api/src/com/cloud/api/commands/AttachVolumeCmd.java +++ b/api/src/com/cloud/api/commands/AttachVolumeCmd.java @@ -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()); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/api/src/com/cloud/api/commands/DeleteVolumeCmd.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/api/commands/DeleteVolumeCmd.java b/api/src/com/cloud/api/commands/DeleteVolumeCmd.java index 22f30eb..e239041 100644 --- a/api/src/com/cloud/api/commands/DeleteVolumeCmd.java +++ b/api/src/com/cloud/api/commands/DeleteVolumeCmd.java @@ -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); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/api/src/com/cloud/offering/DiskOffering.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/offering/DiskOffering.java b/api/src/com/cloud/offering/DiskOffering.java index a937c6d..cd4dbf2 100644 --- a/api/src/com/cloud/offering/DiskOffering.java +++ b/api/src/com/cloud/offering/DiskOffering.java @@ -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(); } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/api/src/com/cloud/storage/pool/StoragePoolService.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/storage/pool/StoragePoolService.java b/api/src/com/cloud/storage/pool/StoragePoolService.java index d0a24f5..64af835 100644 --- a/api/src/com/cloud/storage/pool/StoragePoolService.java +++ b/api/src/com/cloud/storage/pool/StoragePoolService.java @@ -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 { /** http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/api/src/com/cloud/storage/volume/VolumeService.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/storage/volume/VolumeService.java b/api/src/com/cloud/storage/volume/VolumeService.java index 9c207f3..fe310dc 100644 --- a/api/src/com/cloud/storage/volume/VolumeService.java +++ b/api/src/com/cloud/storage/volume/VolumeService.java @@ -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 searchForVolumes(ListVolumesCmd cmd); + + void allocateVolume(Long vmId, Pair rootDiskOffering, + List> dataDiskOfferings, + Long templateId, Account owner); + + void prepareForMigration(VirtualMachineProfile vm, DeployDestination dest); + void prepare(VirtualMachineProfile 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 vm, StoragePool destPool) throws ConcurrentOperationException; + boolean deleteVolume(DeleteVolumeCmd cmd); + void release(VirtualMachineProfile profile); + + void cleanupVolumes(long vmId) throws ConcurrentOperationException; + void recreateVolume(long volumeId, long vmId) throws ConcurrentOperationException; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/core/src/com/cloud/storage/DiskOfferingVO.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/storage/DiskOfferingVO.java b/core/src/com/cloud/storage/DiskOfferingVO.java index 0219840..21a1631 100755 --- a/core/src/com/cloud/storage/DiskOfferingVO.java +++ b/core/src/com/cloud/storage/DiskOfferingVO.java @@ -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") http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/server/src/com/cloud/storage/orchestra/StorageOrchestraEngine.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/orchestra/StorageOrchestraEngine.java b/server/src/com/cloud/storage/orchestra/StorageOrchestraEngine.java deleted file mode 100644 index 31b0ad9..0000000 --- a/server/src/com/cloud/storage/orchestra/StorageOrchestraEngine.java +++ /dev/null @@ -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 vm, DeployDestination dest); - void prepare(VirtualMachineProfile vm, DeployDestination dest, boolean recreate) throws StorageUnavailableException, - InsufficientStorageCapacityException, ConcurrentOperationException; - - void allocateVolume(Long vmId, Pair rootDiskOffering, - List> 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); -} http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/server/src/com/cloud/storage/orchestra/StorageOrchestraEngineImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/orchestra/StorageOrchestraEngineImpl.java b/server/src/com/cloud/storage/orchestra/StorageOrchestraEngineImpl.java index d759228..24fd214 100644 --- a/server/src/com/cloud/storage/orchestra/StorageOrchestraEngineImpl.java +++ b/server/src/com/cloud/storage/orchestra/StorageOrchestraEngineImpl.java @@ -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 rootDiskOffering, - List> dataDiskOfferings, Long templateId, Account owner) { + Pair rootDiskOffering, + List> 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 vm, DeployDestination dest) { - List vols = _volsDao.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)); - } - - if (vm.getType() == VirtualMachine.Type.User) { - UserVmVO userVM = (UserVmVO) vm.getVirtualMachine(); - if (userVM.getIsoId() != null) { - Pair 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); - } - } - } - } + @Override + public void prepareForMigration(VirtualMachineProfile vm, DeployDestination dest) { + List 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)); + } + + 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 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 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 profile) { + List volumes = profile.getDisks(); + for (VolumeTO volumeT : volumes) { + long volumeId = volumeT.getId(); + VolumeVO volume = _volumeDao.findById(volumeId); + _volumeMgr.release(volume); + } + } @Override - public boolean StorageMigration(VirtualMachineProfile vm, StoragePool destPool) throws ConcurrentOperationException { + public boolean vmStorageMigration(VirtualMachineProfile vm, StoragePool destPool) throws ConcurrentOperationException { List vols = _volumeDao.findUsableVolumesForInstance(vm.getId()); List volumesNeedToMigrate = new ArrayList(); @@ -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 vols = new ArrayList(); 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 searchForVolumes(ListVolumesCmd cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List 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 findRecurringSnapshotSchedule(ListRecurringSnapshotScheduleCmd cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List 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 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); + } } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/server/src/com/cloud/storage/pool/StoragePoolManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/pool/StoragePoolManagerImpl.java b/server/src/com/cloud/storage/pool/StoragePoolManagerImpl.java index be9989d..e3318c3 100755 --- a/server/src/com/cloud/storage/pool/StoragePoolManagerImpl.java +++ b/server/src/com/cloud/storage/pool/StoragePoolManagerImpl.java @@ -1933,14 +1933,6 @@ public class StoragePoolManagerImpl implements StoragePoolManager, Manager, Clus } } - - - - @Override - public void release(VirtualMachineProfile profile) { - // add code here - } - protected class StorageGarbageCollector implements Runnable { public StorageGarbageCollector() { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/server/src/com/cloud/storage/volume/VolumeManager.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/volume/VolumeManager.java b/server/src/com/cloud/storage/volume/VolumeManager.java index 432e389..2429ef0 100644 --- a/server/src/com/cloud/storage/volume/VolumeManager.java +++ b/server/src/com/cloud/storage/volume/VolumeManager.java @@ -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; @@ -34,17 +35,6 @@ 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 * @param vm @@ -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 @@ -93,27 +67,16 @@ public interface VolumeManager { * @return VolumeVO a persisted volume. */ DiskProfile allocateVolume(Long vmId, - Pair rootDiskOffering, - List> dataDiskOfferings, Long templateId, Account owner); + Pair rootDiskOffering, + List> 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 volumes, StoragePool destPool) throws ConcurrentOperationException; + + void release(VolumeVO volume); + + void recreateVolume(VolumeVO volume, long vmId) throws ConcurrentOperationException; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/server/src/com/cloud/storage/volume/VolumeManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/volume/VolumeManagerImpl.java b/server/src/com/cloud/storage/volume/VolumeManagerImpl.java index b702590..5833e13 100644 --- a/server/src/com/cloud/storage/volume/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/volume/VolumeManagerImpl.java @@ -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 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; } - - @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; - } - - @Override - public boolean volumeOnSharedStoragePool(VolumeVO volume) { + + private 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; + } + + 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()); - 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 vols = new ArrayList(); - 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 rootDiskOffering, List> dataDiskOfferings, Long templateId, Account owner) { + public DiskProfile allocateVolume(Long vmId, Pair rootDiskOffering, List> 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 offering : dataDiskOfferings) { + for (Pair 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 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 volumesForVm = _volumeDao.findByInstance(vmId); List toBeExpunged = new ArrayList(); - 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); + } } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/server/src/com/cloud/vm/UserVmManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 214b0f1..39e38e4 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -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 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 rootDiskOffering = new Pair(null, null); - List> dataDiskOfferings = new ArrayList>(); + Pair rootDiskOffering = new Pair(null, null); + List> dataDiskOfferings = new ArrayList>(); 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(diskOffering, size)); + dataDiskOfferings.add(new Pair(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 { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/server/src/com/cloud/vm/VirtualMachineManager.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index 18e63fb..2377c4e 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -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 allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, - Pair rootDiskOffering, - List> dataDiskOfferings, + Pair rootDiskOffering, + List> dataDiskOfferings, List> networks, Map params, DeploymentPlan plan, @@ -66,7 +67,7 @@ public interface VirtualMachineManager extends Manager { VMTemplateVO template, ServiceOfferingVO serviceOffering, Long rootSize, - Pair dataDiskOffering, + Pair dataDiskOffering, List> networks, DeploymentPlan plan, HypervisorType hyperType, http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5150aff3/server/src/com/cloud/vm/VirtualMachineManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index be533cf..a494a2c 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -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 allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Pair rootDiskOffering, - List> dataDiskOfferings, List> networks, Map params, DeploymentPlan plan, + public T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Pair rootDiskOffering, + List> dataDiskOfferings, List> networks, Map 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>(0); + dataDiskOfferings = new ArrayList>(0); } if (s_logger.isDebugEnabled()) { @@ -316,13 +317,13 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene } @Override - public T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Long rootSize, Pair dataDiskOffering, + public T allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, Long rootSize, Pair dataDiskOffering, List> networks, DeploymentPlan plan, HypervisorType hyperType, Account owner) throws InsufficientCapacityException { - List> diskOfferings = new ArrayList>(1); + List> diskOfferings = new ArrayList>(1); if (dataDiskOffering != null) { diskOfferings.add(dataDiskOffering); } - return allocate(vm, template, serviceOffering, new Pair(serviceOffering, rootSize), diskOfferings, networks, null, plan, hyperType, owner); + return allocate(vm, template, serviceOffering, new Pair(serviceOffering, rootSize), diskOfferings, networks, null, plan, hyperType, owner); } @Override @@ -1223,7 +1224,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene VirtualMachineProfile profile = new VirtualMachineProfileImpl(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