Skip to content

Commit aad1cda

Browse files
csuich2sudison
authored andcommitted
Added categorized sorting to SnapshotStrategy and DataMotionStrategy
1 parent e514da2 commit aad1cda

14 files changed

Lines changed: 302 additions & 77 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
import com.cloud.host.Host;
2727

2828
public interface DataMotionStrategy {
29-
boolean canHandle(DataObject srcData, DataObject destData);
29+
StrategyPriority.Priority canHandle(DataObject srcData, DataObject destData);
3030

31-
boolean canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost);
31+
StrategyPriority.Priority canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost);
3232

3333
Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
3434

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ public interface SnapshotStrategy {
2727

2828
boolean revertSnapshot(Long snapshotId);
2929

30-
boolean canHandle(Snapshot snapshot);
30+
StrategyPriority.Priority canHandle(Snapshot snapshot);
3131
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.apache.cloudstack.engine.subsystem.api.storage;
2+
3+
import java.util.Collections;
4+
import java.util.Comparator;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
import com.cloud.host.Host;
9+
import com.cloud.storage.Snapshot;
10+
11+
public class StrategyPriority {
12+
public enum Priority {
13+
CANT_HANDLE,
14+
DEFAULT,
15+
HYPERVISOR,
16+
PLUGIN,
17+
HIGHEST
18+
}
19+
20+
public static void sortStrategies(List<SnapshotStrategy> strategies, Snapshot snapshot) {
21+
Collections.sort(strategies, new SnapshotStrategyComparator(snapshot));
22+
}
23+
24+
public static void sortStrategies(List<DataMotionStrategy> strategies, DataObject srcData, DataObject destData) {
25+
Collections.sort(strategies, new DataMotionStrategyComparator(srcData, destData));
26+
}
27+
28+
public static void sortStrategies(List<DataMotionStrategy> strategies, Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
29+
Collections.sort(strategies, new DataMotionStrategyHostComparator(volumeMap, srcHost, destHost));
30+
}
31+
32+
static class SnapshotStrategyComparator implements Comparator<SnapshotStrategy> {
33+
34+
Snapshot snapshot;
35+
36+
public SnapshotStrategyComparator(Snapshot snapshot) {
37+
this.snapshot = snapshot;
38+
}
39+
40+
@Override
41+
public int compare(SnapshotStrategy o1, SnapshotStrategy o2) {
42+
int i1 = o1.canHandle(snapshot).ordinal();
43+
int i2 = o2.canHandle(snapshot).ordinal();
44+
return new Integer(i2).compareTo(new Integer(i1));
45+
}
46+
}
47+
48+
static class DataMotionStrategyComparator implements Comparator<DataMotionStrategy> {
49+
50+
DataObject srcData, destData;
51+
52+
public DataMotionStrategyComparator(DataObject srcData, DataObject destData) {
53+
this.srcData = srcData;
54+
this.destData = destData;
55+
}
56+
57+
@Override
58+
public int compare(DataMotionStrategy o1, DataMotionStrategy o2) {
59+
int i1 = o1.canHandle(srcData, destData).ordinal();
60+
int i2 = o2.canHandle(srcData, destData).ordinal();
61+
return new Integer(i2).compareTo(new Integer(i1));
62+
}
63+
}
64+
65+
static class DataMotionStrategyHostComparator implements Comparator<DataMotionStrategy> {
66+
67+
Host srcHost, destHost;
68+
Map<VolumeInfo, DataStore> volumeMap;
69+
70+
public DataMotionStrategyHostComparator(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
71+
this.volumeMap = volumeMap;
72+
this.srcHost = srcHost;
73+
this.destHost = destHost;
74+
}
75+
76+
@Override
77+
public int compare(DataMotionStrategy o1, DataMotionStrategy o2) {
78+
int i1 = o1.canHandle(volumeMap, srcHost, destHost).ordinal();
79+
int i2 = o2.canHandle(volumeMap, srcHost, destHost).ordinal();
80+
return new Integer(i2).compareTo(new Integer(i1));
81+
}
82+
}
83+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package org.apache.cloudstack.engine.subsystem.api.storage;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority.Priority;
9+
import org.junit.Test;
10+
11+
import com.cloud.host.Host;
12+
import com.cloud.storage.Snapshot;
13+
14+
import static org.junit.Assert.assertEquals;
15+
16+
import static org.mockito.Matchers.any;
17+
import static org.mockito.Mockito.doReturn;
18+
import static org.mockito.Mockito.mock;
19+
20+
public class StrategyPriorityTest {
21+
22+
@Test
23+
public void testSortSnapshotStrategies() {
24+
SnapshotStrategy cantHandleStrategy = mock(SnapshotStrategy.class);
25+
SnapshotStrategy defaultStrategy = mock(SnapshotStrategy.class);
26+
SnapshotStrategy hyperStrategy = mock(SnapshotStrategy.class);
27+
SnapshotStrategy pluginStrategy = mock(SnapshotStrategy.class);
28+
SnapshotStrategy highestStrategy = mock(SnapshotStrategy.class);
29+
30+
doReturn(Priority.CANT_HANDLE).when(cantHandleStrategy).canHandle(any(Snapshot.class));
31+
doReturn(Priority.DEFAULT).when(defaultStrategy).canHandle(any(Snapshot.class));
32+
doReturn(Priority.HYPERVISOR).when(hyperStrategy).canHandle(any(Snapshot.class));
33+
doReturn(Priority.PLUGIN).when(pluginStrategy).canHandle(any(Snapshot.class));
34+
doReturn(Priority.HIGHEST).when(highestStrategy).canHandle(any(Snapshot.class));
35+
36+
List<SnapshotStrategy> strategies = new ArrayList<SnapshotStrategy>(5);
37+
strategies.addAll(Arrays.asList(defaultStrategy, pluginStrategy, hyperStrategy, cantHandleStrategy, highestStrategy));
38+
39+
StrategyPriority.sortStrategies(strategies, mock(Snapshot.class));
40+
41+
assertEquals("Highest was not 1st.", highestStrategy, strategies.get(0));
42+
assertEquals("Plugin was not 2nd.", pluginStrategy, strategies.get(1));
43+
assertEquals("Hypervisor was not 3rd.", hyperStrategy, strategies.get(2));
44+
assertEquals("Default was not 4th.", defaultStrategy, strategies.get(3));
45+
assertEquals("Can't Handle was not 5th.", cantHandleStrategy, strategies.get(4));
46+
}
47+
48+
@Test
49+
public void testSortDataMotionStrategies() {
50+
DataMotionStrategy cantHandleStrategy = mock(DataMotionStrategy.class);
51+
DataMotionStrategy defaultStrategy = mock(DataMotionStrategy.class);
52+
DataMotionStrategy hyperStrategy = mock(DataMotionStrategy.class);
53+
DataMotionStrategy pluginStrategy = mock(DataMotionStrategy.class);
54+
DataMotionStrategy highestStrategy = mock(DataMotionStrategy.class);
55+
56+
doReturn(Priority.CANT_HANDLE).when(cantHandleStrategy).canHandle(any(DataObject.class), any(DataObject.class));
57+
doReturn(Priority.DEFAULT).when(defaultStrategy).canHandle(any(DataObject.class), any(DataObject.class));
58+
doReturn(Priority.HYPERVISOR).when(hyperStrategy).canHandle(any(DataObject.class), any(DataObject.class));
59+
doReturn(Priority.PLUGIN).when(pluginStrategy).canHandle(any(DataObject.class), any(DataObject.class));
60+
doReturn(Priority.HIGHEST).when(highestStrategy).canHandle(any(DataObject.class), any(DataObject.class));
61+
62+
List<DataMotionStrategy> strategies = new ArrayList<DataMotionStrategy>(5);
63+
strategies.addAll(Arrays.asList(defaultStrategy, pluginStrategy, hyperStrategy, cantHandleStrategy, highestStrategy));
64+
65+
StrategyPriority.sortStrategies(strategies, mock(DataObject.class), mock(DataObject.class));
66+
67+
assertEquals("Highest was not 1st.", highestStrategy, strategies.get(0));
68+
assertEquals("Plugin was not 2nd.", pluginStrategy, strategies.get(1));
69+
assertEquals("Hypervisor was not 3rd.", hyperStrategy, strategies.get(2));
70+
assertEquals("Default was not 4th.", defaultStrategy, strategies.get(3));
71+
assertEquals("Can't Handle was not 5th.", cantHandleStrategy, strategies.get(4));
72+
}
73+
74+
@Test
75+
@SuppressWarnings("unchecked")
76+
public void testSortDataMotionStrategies2() {
77+
DataMotionStrategy cantHandleStrategy = mock(DataMotionStrategy.class);
78+
DataMotionStrategy defaultStrategy = mock(DataMotionStrategy.class);
79+
DataMotionStrategy hyperStrategy = mock(DataMotionStrategy.class);
80+
DataMotionStrategy pluginStrategy = mock(DataMotionStrategy.class);
81+
DataMotionStrategy highestStrategy = mock(DataMotionStrategy.class);
82+
83+
doReturn(Priority.CANT_HANDLE).when(cantHandleStrategy).canHandle(any(Map.class), any(Host.class), any(Host.class));
84+
doReturn(Priority.DEFAULT).when(defaultStrategy).canHandle(any(Map.class), any(Host.class), any(Host.class));
85+
doReturn(Priority.HYPERVISOR).when(hyperStrategy).canHandle(any(Map.class), any(Host.class), any(Host.class));
86+
doReturn(Priority.PLUGIN).when(pluginStrategy).canHandle(any(Map.class), any(Host.class), any(Host.class));
87+
doReturn(Priority.HIGHEST).when(highestStrategy).canHandle(any(Map.class), any(Host.class), any(Host.class));
88+
89+
List<DataMotionStrategy> strategies = new ArrayList<DataMotionStrategy>(5);
90+
strategies.addAll(Arrays.asList(defaultStrategy, pluginStrategy, hyperStrategy, cantHandleStrategy, highestStrategy));
91+
92+
StrategyPriority.sortStrategies(strategies, mock(Map.class), mock(Host.class), mock(Host.class));
93+
94+
assertEquals("Highest was not 1st.", highestStrategy, strategies.get(0));
95+
assertEquals("Plugin was not 2nd.", pluginStrategy, strategies.get(1));
96+
assertEquals("Hypervisor was not 3rd.", hyperStrategy, strategies.get(2));
97+
assertEquals("Default was not 4th.", defaultStrategy, strategies.get(3));
98+
assertEquals("Can't Handle was not 5th.", cantHandleStrategy, strategies.get(4));
99+
}
100+
}

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
3737
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
3838
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
39+
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority.Priority;
3940
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
4041
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
4142
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
@@ -123,14 +124,13 @@
123124
ManagementService _mgmtServer;
124125

125126
@Override
126-
public boolean canHandle(DataObject srcData, DataObject destData) {
127-
// TODO Auto-generated method stub
128-
return true;
127+
public Priority canHandle(DataObject srcData, DataObject destData) {
128+
return Priority.DEFAULT;
129129
}
130130

131131
@Override
132-
public boolean canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
133-
return false;
132+
public Priority canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
133+
return Priority.CANT_HANDLE;
134134
}
135135

136136
protected boolean needCacheStorage(DataObject srcData, DataObject destData) {

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,25 @@
1818
*/
1919
package org.apache.cloudstack.storage.motion;
2020

21-
import com.cloud.agent.api.to.VirtualMachineTO;
22-
import com.cloud.host.Host;
23-
import com.cloud.utils.exception.CloudRuntimeException;
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
import javax.inject.Inject;
25+
2426
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
2527
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
2628
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
2729
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
2830
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
31+
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
32+
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority.Priority;
2933
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
3034
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
3135
import org.springframework.stereotype.Component;
3236

33-
import javax.inject.Inject;
34-
import java.util.List;
35-
import java.util.Map;
37+
import com.cloud.agent.api.to.VirtualMachineTO;
38+
import com.cloud.host.Host;
39+
import com.cloud.utils.exception.CloudRuntimeException;
3640

3741
@Component
3842
public class DataMotionServiceImpl implements DataMotionService {
@@ -53,8 +57,10 @@ public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCa
5357
return;
5458
}
5559

60+
StrategyPriority.sortStrategies(strategies, srcData, destData);
61+
5662
for (DataMotionStrategy strategy : strategies) {
57-
if (strategy.canHandle(srcData, destData)) {
63+
if (strategy.canHandle(srcData, destData) != Priority.CANT_HANDLE) {
5864
strategy.copyAsync(srcData, destData, callback);
5965
return;
6066
}
@@ -65,8 +71,11 @@ public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCa
6571
@Override
6672
public void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost,
6773
AsyncCompletionCallback<CopyCommandResult> callback) {
74+
75+
StrategyPriority.sortStrategies(strategies, volumeMap, srcHost, destHost);
76+
6877
for (DataMotionStrategy strategy : strategies) {
69-
if (strategy.canHandle(volumeMap, srcHost, destHost)) {
78+
if (strategy.canHandle(volumeMap, srcHost, destHost) != Priority.CANT_HANDLE) {
7079
strategy.copyAsync(volumeMap, vmTo, srcHost, destHost, callback);
7180
return;
7281
}

engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,40 +21,39 @@
2121
import java.util.Map;
2222
import java.util.UUID;
2323

24-
import com.cloud.agent.api.to.DataObjectType;
25-
import com.cloud.agent.api.to.DataTO;
26-
import com.cloud.storage.Storage;
2724
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
2825
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
2926
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
3027
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
3128
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
29+
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority.Priority;
3230
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
3331
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
34-
35-
import com.cloud.agent.api.to.VirtualMachineTO;
36-
import com.cloud.host.Host;
3732
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
38-
import org.apache.cloudstack.storage.snapshot.SnapshotObject;
3933
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
4034
import org.apache.cloudstack.storage.to.TemplateObjectTO;
4135

36+
import com.cloud.agent.api.to.DataObjectType;
37+
import com.cloud.agent.api.to.DataTO;
38+
import com.cloud.agent.api.to.VirtualMachineTO;
39+
import com.cloud.host.Host;
40+
import com.cloud.storage.Storage;
41+
4242
public class MockStorageMotionStrategy implements DataMotionStrategy {
4343

4444
boolean success = true;
4545
@Override
46-
public boolean canHandle(DataObject srcData, DataObject destData) {
47-
// TODO Auto-generated method stub
48-
return true;
46+
public Priority canHandle(DataObject srcData, DataObject destData) {
47+
return Priority.HIGHEST;
4948
}
5049

5150
public void makeBackupSnapshotSucceed(boolean success) {
5251
this.success = success;
5352
}
5453

5554
@Override
56-
public boolean canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
57-
return true;
55+
public Priority canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
56+
return Priority.HIGHEST;
5857
}
5958

6059
@Override

0 commit comments

Comments
 (0)