Updated Branches: refs/heads/4.2 4b8d636ce -> 746896b12
CLOUDSTACK-4939 - Failed to create snapshot (KVM, Multiple hosts, Sharedstorage) Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/746896b1 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/746896b1 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/746896b1 Branch: refs/heads/4.2 Commit: 746896b1296bfb2911c4665731e3388f872e38b0 Parents: 4b8d636 Author: Edison Su <[email protected]> Authored: Wed Oct 30 14:04:41 2013 -0700 Committer: Edison Su <[email protected]> Committed: Wed Oct 30 14:04:41 2013 -0700 ---------------------------------------------------------------------- .../subsystem/api/storage/EndPointSelector.java | 4 ++ .../subsystem/api/storage/StorageAction.java | 25 +++++++++++ .../subsystem/api/storage/VolumeInfo.java | 2 + .../motion/AncientDataMotionStrategy.java | 20 ++------- .../endpoint/DefaultEndPointSelector.java | 45 +++++++++++++++++--- .../cloudstack/storage/volume/VolumeObject.java | 10 +++++ .../CloudStackPrimaryDataStoreDriverImpl.java | 4 +- 7 files changed, 86 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/746896b1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java index ca0cc2c..01de4f8 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java @@ -23,9 +23,13 @@ import java.util.List; public interface EndPointSelector { EndPoint select(DataObject srcData, DataObject destData); + EndPoint select(DataObject srcData, DataObject destData, StorageAction action); + EndPoint select(DataObject object); EndPoint select(DataStore store); + EndPoint select(DataObject object, StorageAction action); + List<EndPoint> selectAll(DataStore store); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/746896b1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageAction.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageAction.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageAction.java new file mode 100644 index 0000000..4fbb20e --- /dev/null +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/StorageAction.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.engine.subsystem.api.storage; + +public enum StorageAction { + TAKESNAPSHOT, + BACKUPSNAPSHOT, + DELETESNAPSHOT +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/746896b1/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java index 3b4aba9..30bb870 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java @@ -21,6 +21,7 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import com.cloud.agent.api.Answer; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Volume; +import com.cloud.vm.VirtualMachine; public interface VolumeInfo extends DataObject, Volume { boolean isAttachedVM(); @@ -34,6 +35,7 @@ public interface VolumeInfo extends DataObject, Volume { Long getLastPoolId(); String getAttachedVmName(); + VirtualMachine getAttachedVM(); void processEventOnly(ObjectInDataStoreStateMachine.Event event); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/746896b1/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java ---------------------------------------------------------------------- diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java index dce8c4e..c69046e 100644 --- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java +++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java @@ -22,22 +22,8 @@ import java.util.Map; import javax.inject.Inject; -import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; -import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +import org.apache.cloudstack.engine.subsystem.api.storage.*; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; -import org.apache.cloudstack.engine.subsystem.api.storage.Scope; -import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; @@ -463,11 +449,11 @@ public class CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait, _mgmtServer.getExecuteInSequence()); cmd.setCacheTO(cacheData.getTO()); - EndPoint ep = selector.select(srcData, destData); + EndPoint ep = selector.select(srcData, destData, StorageAction.BACKUPSNAPSHOT); answer = ep.sendMessage(cmd); } else { CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait, _mgmtServer.getExecuteInSequence()); - EndPoint ep = selector.select(srcData, destData); + EndPoint ep = selector.select(srcData, destData, StorageAction.BACKUPSNAPSHOT); answer = ep.sendMessage(cmd); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/746896b1/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java index 98c6a3f..0c9c78b 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java +++ b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java @@ -27,11 +27,9 @@ import java.util.List; import javax.inject.Inject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; -import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; -import org.apache.cloudstack.engine.subsystem.api.storage.Scope; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.*; import org.apache.cloudstack.storage.RemoteHostEndPoint; import org.apache.cloudstack.storage.LocalHostEndpoint; import org.apache.log4j.Logger; @@ -194,6 +192,21 @@ public class DefaultEndPointSelector implements EndPointSelector { return null; } + @Override + public EndPoint select(DataObject srcData, DataObject destData, StorageAction action) { + if (action == StorageAction.BACKUPSNAPSHOT) { + SnapshotInfo srcSnapshot = (SnapshotInfo)srcData; + if (srcSnapshot.getHypervisorType() == Hypervisor.HypervisorType.KVM) { + VolumeInfo volumeInfo = srcSnapshot.getBaseVolume(); + VirtualMachine vm = volumeInfo.getAttachedVM(); + if (vm != null && vm.getState() == VirtualMachine.State.Running) { + return getEndPointFromHostId(vm.getHostId()); + } + } + } + return select(srcData, destData); + } + protected EndPoint findEndpointForPrimaryStorage(DataStore store) { return findEndPointInScope(store.getScope(), findOneHostOnPrimaryStorage, store.getId()); } @@ -250,6 +263,28 @@ public class DefaultEndPointSelector implements EndPointSelector { } } + private EndPoint getEndPointFromHostId(Long hostId) { + HostVO host = hostDao.findById(hostId); + return RemoteHostEndPoint.getHypervisorHostEndPoint(host.getId(), host.getPrivateIpAddress(), + host.getPublicIpAddress()); + } + + @Override + public EndPoint select(DataObject object, StorageAction action) { + if (action == StorageAction.TAKESNAPSHOT) { + SnapshotInfo snapshotInfo = (SnapshotInfo)object; + if (snapshotInfo.getHypervisorType() == Hypervisor.HypervisorType.KVM) { + VolumeInfo volumeInfo = snapshotInfo.getBaseVolume(); + VirtualMachine vm = volumeInfo.getAttachedVM(); + if ((vm != null) && (vm.getState() == VirtualMachine.State.Running)) { + Long hostId = vm.getHostId(); + return getEndPointFromHostId(hostId); + } + } + } + return select(object); + } + @Override public List<EndPoint> selectAll(DataStore store) { List<EndPoint> endPoints = new ArrayList<EndPoint>(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/746896b1/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java ---------------------------------------------------------------------- diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java index f5a1276..5dac5f7 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -22,6 +22,7 @@ import javax.inject.Inject; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.vm.VirtualMachine; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; @@ -99,6 +100,15 @@ public class VolumeObject implements VolumeInfo { } @Override + public VirtualMachine getAttachedVM() { + Long vmId = this.volumeVO.getInstanceId(); + if (vmId != null) { + VMInstanceVO vm = vmInstanceDao.findById(vmId); + return vm; + } + return null; + } + @Override public String getUuid() { return volumeVO.getUuid(); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/746896b1/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java ---------------------------------------------------------------------- diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index 683239c..036f3f5 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -232,10 +232,10 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri DataTO snapshotTO = snapshot.getTO(); CreateObjectCommand cmd = new CreateObjectCommand(snapshotTO); - EndPoint ep = this.epSelector.select(snapshot); + EndPoint ep = this.epSelector.select(snapshot, StorageAction.TAKESNAPSHOT); Answer answer = null; if ( ep == null ){ - String errMsg = "No remote endpoint to send DeleteCommand, check if host or ssvm is down?"; + String errMsg = "No remote endpoint to send createObjectCommand, check if host or ssvm is down?"; s_logger.error(errMsg); answer = new Answer(cmd, false, errMsg); } else{
