Skip to content

Commit 0824c78

Browse files
committed
CLOUDSTACK-4939 - Failed to create snapshot (KVM, Multiple hosts, Sharedstorage)
Conflicts: engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java Conflicts: engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
1 parent 8caf52c commit 0824c78

7 files changed

Lines changed: 95 additions & 21 deletions

File tree

engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@
2323
public interface EndPointSelector {
2424
EndPoint select(DataObject srcData, DataObject destData);
2525

26+
EndPoint select(DataObject srcData, DataObject destData, StorageAction action);
27+
2628
EndPoint select(DataObject object);
2729

2830
EndPoint select(DataStore store);
2931

32+
EndPoint select(DataObject object, StorageAction action);
33+
3034
List<EndPoint> selectAll(DataStore store);
3135

3236
EndPoint select(Scope scope, Long storeId);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.cloudstack.engine.subsystem.api.storage;
20+
21+
public enum StorageAction {
22+
TAKESNAPSHOT,
23+
BACKUPSNAPSHOT,
24+
DELETESNAPSHOT
25+
}

engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.cloud.hypervisor.Hypervisor.HypervisorType;
2323
import com.cloud.offering.DiskOffering.DiskCacheMode;
2424
import com.cloud.storage.Volume;
25+
import com.cloud.vm.VirtualMachine;
2526

2627
public interface VolumeInfo extends DataObject, Volume {
2728
boolean isAttachedVM();
@@ -35,6 +36,7 @@ public interface VolumeInfo extends DataObject, Volume {
3536
Long getLastPoolId();
3637

3738
String getAttachedVmName();
39+
VirtualMachine getAttachedVM();
3840

3941
void processEventOnly(ObjectInDataStoreStateMachine.Event event);
4042

engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,7 @@
2323

2424
import javax.inject.Inject;
2525

26-
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
27-
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
28-
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
29-
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
30-
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
31-
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
32-
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
33-
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
34-
import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
26+
import org.apache.cloudstack.engine.subsystem.api.storage.*;
3527
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
3628
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
3729
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
@@ -498,14 +490,15 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
498490
} else {
499491
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait, VirtualMachineManager.ExecuteInSequence.value());
500492
cmd.setOptions(options);
501-
EndPoint ep = selector.select(srcData, destData);
493+
EndPoint ep = selector.select(srcData, destData, StorageAction.BACKUPSNAPSHOT);
502494
if (ep == null) {
503495
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
504496
s_logger.error(errMsg);
505497
answer = new Answer(cmd, false, errMsg);
506498
} else {
507499
answer = ep.sendMessage(cmd);
508500
}
501+
509502
}
510503
// clean up cache entry
511504
if (cacheData != null) {

engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,25 @@
2727

2828
import javax.inject.Inject;
2929

30-
import com.cloud.utils.db.Transaction;
31-
import org.apache.log4j.Logger;
32-
import org.springframework.stereotype.Component;
33-
3430
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
3531
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
3632
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
3733
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
3834
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
35+
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
36+
import org.apache.cloudstack.engine.subsystem.api.storage.StorageAction;
3937
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
38+
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
4039
import org.apache.cloudstack.storage.LocalHostEndpoint;
4140
import org.apache.cloudstack.storage.RemoteHostEndPoint;
41+
import org.apache.log4j.Logger;
42+
import org.springframework.stereotype.Component;
4243

4344
import com.cloud.host.Host;
4445
import com.cloud.host.HostVO;
4546
import com.cloud.host.Status;
4647
import com.cloud.host.dao.HostDao;
48+
import com.cloud.hypervisor.Hypervisor;
4749
import com.cloud.storage.DataStoreRole;
4850
import com.cloud.storage.ScopeType;
4951
import com.cloud.storage.Storage.TemplateType;
@@ -52,6 +54,7 @@
5254
import com.cloud.utils.db.SearchCriteria.Op;
5355
import com.cloud.utils.db.TransactionLegacy;
5456
import com.cloud.utils.exception.CloudRuntimeException;
57+
import com.cloud.vm.VirtualMachine;
5558

5659
@Component
5760
public class DefaultEndPointSelector implements EndPointSelector {
@@ -206,6 +209,21 @@ public EndPoint select(DataObject srcData, DataObject destData) {
206209
return null;
207210
}
208211

212+
@Override
213+
public EndPoint select(DataObject srcData, DataObject destData, StorageAction action) {
214+
if (action == StorageAction.BACKUPSNAPSHOT) {
215+
SnapshotInfo srcSnapshot = (SnapshotInfo)srcData;
216+
if (srcSnapshot.getHypervisorType() == Hypervisor.HypervisorType.KVM) {
217+
VolumeInfo volumeInfo = srcSnapshot.getBaseVolume();
218+
VirtualMachine vm = volumeInfo.getAttachedVM();
219+
if (vm != null && vm.getState() == VirtualMachine.State.Running) {
220+
return getEndPointFromHostId(vm.getHostId());
221+
}
222+
}
223+
}
224+
return select(srcData, destData);
225+
}
226+
209227
protected EndPoint findEndpointForPrimaryStorage(DataStore store) {
210228
return findEndPointInScope(store.getScope(), findOneHostOnPrimaryStorage, store.getId());
211229
}
@@ -268,6 +286,27 @@ public EndPoint select(DataStore store) {
268286
}
269287
}
270288

289+
private EndPoint getEndPointFromHostId(Long hostId) {
290+
HostVO host = hostDao.findById(hostId);
291+
return RemoteHostEndPoint.getHypervisorHostEndPoint(host);
292+
}
293+
294+
@Override
295+
public EndPoint select(DataObject object, StorageAction action) {
296+
if (action == StorageAction.TAKESNAPSHOT) {
297+
SnapshotInfo snapshotInfo = (SnapshotInfo)object;
298+
if (snapshotInfo.getHypervisorType() == Hypervisor.HypervisorType.KVM) {
299+
VolumeInfo volumeInfo = snapshotInfo.getBaseVolume();
300+
VirtualMachine vm = volumeInfo.getAttachedVM();
301+
if ((vm != null) && (vm.getState() == VirtualMachine.State.Running)) {
302+
Long hostId = vm.getHostId();
303+
return getEndPointFromHostId(hostId);
304+
}
305+
}
306+
}
307+
return select(object);
308+
}
309+
271310
@Override
272311
public EndPoint select(Scope scope, Long storeId) {
273312
return findEndPointInScope(scope, findOneHostOnPrimaryStorage, storeId);

engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
import org.apache.log4j.Logger;
2424

25+
import com.cloud.storage.DiskOfferingVO;
26+
import com.cloud.storage.dao.DiskOfferingDao;
27+
import com.cloud.vm.VirtualMachine;
2528
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
2629
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
2730
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
@@ -40,11 +43,9 @@
4043
import com.cloud.hypervisor.Hypervisor.HypervisorType;
4144
import com.cloud.offering.DiskOffering.DiskCacheMode;
4245
import com.cloud.storage.DataStoreRole;
43-
import com.cloud.storage.DiskOfferingVO;
4446
import com.cloud.storage.Storage.ImageFormat;
4547
import com.cloud.storage.Volume;
4648
import com.cloud.storage.VolumeVO;
47-
import com.cloud.storage.dao.DiskOfferingDao;
4849
import com.cloud.storage.dao.VolumeDao;
4950
import com.cloud.utils.component.ComponentContext;
5051
import com.cloud.utils.exception.CloudRuntimeException;
@@ -100,6 +101,15 @@ public String getAttachedVmName() {
100101
return null;
101102
}
102103

104+
@Override
105+
public VirtualMachine getAttachedVM() {
106+
Long vmId = this.volumeVO.getInstanceId();
107+
if (vmId != null) {
108+
VMInstanceVO vm = vmInstanceDao.findById(vmId);
109+
return vm;
110+
}
111+
return null;
112+
}
103113
@Override
104114
public String getUuid() {
105115
return volumeVO.getUuid();

plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
import javax.inject.Inject;
2626

27-
import org.apache.log4j.Logger;
28-
2927
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
3028
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
3129
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
@@ -37,6 +35,7 @@
3735
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
3836
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
3937
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
38+
import org.apache.cloudstack.engine.subsystem.api.storage.StorageAction;
4039
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
4140
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
4241
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@@ -51,6 +50,7 @@
5150
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
5251
import org.apache.cloudstack.storage.to.TemplateObjectTO;
5352
import org.apache.cloudstack.storage.volume.VolumeObject;
53+
import org.apache.log4j.Logger;
5454

5555
import com.cloud.agent.api.Answer;
5656
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
@@ -269,10 +269,11 @@ public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCm
269269
}
270270

271271
CreateObjectCommand cmd = new CreateObjectCommand(snapshotTO);
272-
EndPoint ep = epSelector.select(snapshot);
272+
EndPoint ep = this.epSelector.select(snapshot, StorageAction.TAKESNAPSHOT);
273273
Answer answer = null;
274-
if (ep == null) {
275-
String errMsg = "No remote endpoint to send DeleteCommand, check if host or ssvm is down?";
274+
275+
if ( ep == null ){
276+
String errMsg = "No remote endpoint to send createObjectCommand, check if host or ssvm is down?";
276277
s_logger.error(errMsg);
277278
answer = new Answer(cmd, false, errMsg);
278279
} else {

0 commit comments

Comments
 (0)