Skip to content

Commit af72fde

Browse files
author
Mike Tutkowski
committed
CLOUDSTACK-9620: Enhancements for managed storage
Allowed zone-wide primary storage based on a custom plug-in to be added via the GUI in a KVM-only environment (previously this only worked for XenServer and VMware) Added support for root disks on managed storage with KVM Added support for volume snapshots with managed storage on KVM Enable creating a template directly from a volume (i.e. without having to go through a volume snapshot) on KVM with managed storage Only allow the resizing of a volume for managed storage on KVM if the volume in question is either not attached to a VM or is attached to a VM in the Stopped state. Included support for Reinstall VM on KVM with managed storage Enabled offline migration on KVM from non-managed storage to managed storage and vice versa Included support for online storage migration on KVM with managed storage (NFS and Ceph to managed storage) Added support to download (extract) a managed-storage volume to a QCOW2 file When uploading a file from outside of CloudStack to CloudStack, set the min and max IOPS, if applicable. Included support for the KVM auto-convergence feature The compression flag was actually added in version 1.0.3 (1000003) as opposed to version 1.3.0 (1003000) (changed this to reflect the correct version) On KVM when using iSCSI-based managed storage, if the user shuts a VM down from the guest OS (as opposed to doing so from CloudStack), we need to pass to the KVM agent a list of applicable iSCSI volumes that need to be disconnected. Added a new Global Setting: kvm.storage.live.migration.wait For XenServer, added a check to enforce that only volumes from zone-wide managed storage can be storage motioned from a host in one cluster to a host in another cluster (cannot do so at the time being with volumes from cluster-scoped managed storage) Don’t allow Storage XenMotion on a VM that has any managed-storage volume with one or more snapshots. Enabled for managed storage with VMware: Template caching, create snapshot, delete snapshot, create volume from snapshot, and create template from snapshot Added an SIOC API plug-in to support VMware SIOC When starting a VM that uses managed storage in a cluster other than the one it last was running in, we need to remove the reference to the iSCSI volume from the original cluster. Added the ability to revert a volume to a snapshot Enabled cluster-scoped managed storage Added support for VMware dynamic discovery
1 parent 3ee8d83 commit af72fde

File tree

86 files changed

+9082
-1285
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+9082
-1285
lines changed

api/src/com/cloud/agent/api/to/DiskTO.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class DiskTO {
2727
public static final String CHAP_INITIATOR_SECRET = "chapInitiatorSecret";
2828
public static final String CHAP_TARGET_USERNAME = "chapTargetUsername";
2929
public static final String CHAP_TARGET_SECRET = "chapTargetSecret";
30+
public static final String SCSI_NAA_DEVICE_ID = "scsiNaaDeviceId";
3031
public static final String MANAGED = "managed";
3132
public static final String IQN = "iqn";
3233
public static final String STORAGE_HOST = "storageHost";
@@ -36,6 +37,9 @@ public class DiskTO {
3637
public static final String PROTOCOL_TYPE = "protocoltype";
3738
public static final String PATH = "path";
3839
public static final String UUID = "uuid";
40+
public static final String VMDK = "vmdk";
41+
public static final String EXPAND_DATASTORE = "expandDatastore";
42+
public static final String TEMPLATE_RESIGN = "templateResign";
3943

4044
private DataTO data;
4145
private Long diskSeq;

api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ public class ResizeVolumeCmd extends BaseAsyncCmd {
7878
/////////////////// Accessors ///////////////////////
7979
/////////////////////////////////////////////////////
8080

81+
public ResizeVolumeCmd() {}
82+
83+
public ResizeVolumeCmd(Long id, Long minIops, Long maxIops) {
84+
this.id = id;
85+
this.minIops = minIops;
86+
this.maxIops = maxIops;
87+
}
88+
8189
//TODO use the method getId() instead of this one.
8290
public Long getEntityId() {
8391
return id;

client/pom.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,21 @@
11471147
</dependency>
11481148
</dependencies>
11491149
</profile>
1150+
<profile>
1151+
<id>sfsioc</id>
1152+
<activation>
1153+
<property>
1154+
<name>noredist</name>
1155+
</property>
1156+
</activation>
1157+
<dependencies>
1158+
<dependency>
1159+
<groupId>org.apache.cloudstack</groupId>
1160+
<artifactId>cloud-plugin-api-solidfire-sioc</artifactId>
1161+
<version>${project.version}</version>
1162+
</dependency>
1163+
</dependencies>
1164+
</profile>
11501165
<profile>
11511166
<id>quickcloud</id>
11521167
<activation>

core/src/com/cloud/agent/api/MigrateCommand.java

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,20 @@
1919

2020
package com.cloud.agent.api;
2121

22+
import java.util.HashMap;
23+
import java.util.Map;
24+
2225
import com.cloud.agent.api.to.VirtualMachineTO;
2326

2427
public class MigrateCommand extends Command {
25-
String vmName;
26-
String destIp;
27-
String hostGuid;
28-
boolean isWindows;
29-
VirtualMachineTO vmTO;
30-
boolean executeInSequence = false;
28+
private String vmName;
29+
private String destIp;
30+
private Map<String, MigrateDiskInfo> migrateStorage;
31+
private boolean autoConvergence;
32+
private String hostGuid;
33+
private boolean isWindows;
34+
private VirtualMachineTO vmTO;
35+
private boolean executeInSequence = false;
3136

3237
protected MigrateCommand() {
3338
}
@@ -40,6 +45,26 @@ public MigrateCommand(String vmName, String destIp, boolean isWindows, VirtualMa
4045
this.executeInSequence = executeInSequence;
4146
}
4247

48+
public void setMigrateStorage(Map<String, MigrateDiskInfo> migrateStorage) {
49+
this.migrateStorage = migrateStorage;
50+
}
51+
52+
public Map<String, MigrateDiskInfo> getMigrateStorage() {
53+
return migrateStorage != null ? new HashMap<>(migrateStorage) : new HashMap<String, MigrateDiskInfo>();
54+
}
55+
56+
public boolean isMigrateStorage() {
57+
return migrateStorage != null && !migrateStorage.isEmpty();
58+
}
59+
60+
public void setAutoConvergence(boolean autoConvergence) {
61+
this.autoConvergence = autoConvergence;
62+
}
63+
64+
public boolean isAutoConvergence() {
65+
return autoConvergence;
66+
}
67+
4368
public boolean isWindows() {
4469
return isWindows;
4570
}
@@ -68,4 +93,79 @@ public String getHostGuid() {
6893
public boolean executeInSequence() {
6994
return executeInSequence;
7095
}
96+
97+
public static class MigrateDiskInfo {
98+
public enum DiskType {
99+
FILE, BLOCK;
100+
101+
@Override
102+
public String toString() {
103+
switch(this) {
104+
case FILE: return "file";
105+
case BLOCK: return "block";
106+
default: throw new IllegalArgumentException();
107+
}
108+
}
109+
}
110+
111+
public enum DriverType {
112+
QCOW2, RAW;
113+
114+
@Override
115+
public String toString() {
116+
switch(this) {
117+
case QCOW2: return "qcow2";
118+
case RAW: return "raw";
119+
default: throw new IllegalArgumentException();
120+
}
121+
}
122+
}
123+
124+
public enum Source {
125+
FILE, DEV;
126+
127+
@Override
128+
public String toString() {
129+
switch(this) {
130+
case FILE: return "file";
131+
case DEV: return "dev";
132+
default: throw new IllegalArgumentException();
133+
}
134+
}
135+
}
136+
137+
private final String serialNumber;
138+
private final DiskType diskType;
139+
private final DriverType driverType;
140+
private final Source source;
141+
private final String sourceText;
142+
143+
public MigrateDiskInfo(final String serialNumber, final DiskType diskType, final DriverType driverType, final Source source, final String sourceText) {
144+
this.serialNumber = serialNumber;
145+
this.diskType = diskType;
146+
this.driverType = driverType;
147+
this.source = source;
148+
this.sourceText = sourceText;
149+
}
150+
151+
public String getSerialNumber() {
152+
return serialNumber;
153+
}
154+
155+
public DiskType getDiskType() {
156+
return diskType;
157+
}
158+
159+
public DriverType getDriverType() {
160+
return driverType;
161+
}
162+
163+
public Source getSource() {
164+
return source;
165+
}
166+
167+
public String getSourceText() {
168+
return sourceText;
169+
}
170+
}
71171
}

core/src/com/cloud/agent/api/ModifyTargetsAnswer.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,16 @@
1919

2020
package com.cloud.agent.api;
2121

22+
import java.util.List;
23+
2224
public class ModifyTargetsAnswer extends Answer {
25+
private List<String> connectedPaths;
26+
27+
public void setConnectedPaths(List<String> connectedPaths) {
28+
this.connectedPaths = connectedPaths;
29+
}
30+
31+
public List<String> getConnectedPaths() {
32+
return connectedPaths;
33+
}
2334
}

core/src/com/cloud/agent/api/ModifyTargetsCommand.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323
import java.util.Map;
2424

2525
public class ModifyTargetsCommand extends Command {
26+
public enum TargetTypeToRemove { BOTH, NEITHER, STATIC, DYNAMIC }
27+
2628
public static final String IQN = "iqn";
29+
public static final String STORAGE_TYPE = "storageType";
30+
public static final String STORAGE_UUID = "storageUuid";
2731
public static final String STORAGE_HOST = "storageHost";
2832
public static final String STORAGE_PORT = "storagePort";
2933
public static final String CHAP_NAME = "chapName";
@@ -32,6 +36,9 @@ public class ModifyTargetsCommand extends Command {
3236
public static final String MUTUAL_CHAP_SECRET = "mutualChapSecret";
3337

3438
private boolean add;
39+
private boolean applyToAllHostsInCluster;
40+
private TargetTypeToRemove targetTypeToRemove = TargetTypeToRemove.BOTH;
41+
private boolean removeAsync;
3542
private List<Map<String, String>> targets;
3643

3744
public void setAdd(boolean add) {
@@ -42,6 +49,30 @@ public boolean getAdd() {
4249
return add;
4350
}
4451

52+
public void setApplyToAllHostsInCluster(boolean applyToAllHostsInCluster) {
53+
this.applyToAllHostsInCluster = applyToAllHostsInCluster;
54+
}
55+
56+
public boolean getApplyToAllHostsInCluster() {
57+
return applyToAllHostsInCluster;
58+
}
59+
60+
public void setTargetTypeToRemove(TargetTypeToRemove targetTypeToRemove) {
61+
this.targetTypeToRemove = targetTypeToRemove;
62+
}
63+
64+
public TargetTypeToRemove getTargetTypeToRemove() {
65+
return targetTypeToRemove;
66+
}
67+
68+
public void setRemoveAsync(boolean removeAsync) {
69+
this.removeAsync = removeAsync;
70+
}
71+
72+
public boolean isRemoveAsync() {
73+
return removeAsync;
74+
}
75+
4576
public void setTargets(List<Map<String, String>> targets) {
4677
this.targets = targets;
4778
}

core/src/com/cloud/agent/api/PrepareForMigrationCommand.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
import com.cloud.agent.api.to.VirtualMachineTO;
2323

2424
public class PrepareForMigrationCommand extends Command {
25-
VirtualMachineTO vm;
25+
private VirtualMachineTO vm;
26+
private boolean rollback;
2627

2728
protected PrepareForMigrationCommand() {
2829
}
@@ -35,6 +36,14 @@ public VirtualMachineTO getVirtualMachine() {
3536
return vm;
3637
}
3738

39+
public void setRollback(boolean rollback) {
40+
this.rollback = rollback;
41+
}
42+
43+
public boolean isRollback() {
44+
return rollback;
45+
}
46+
3847
@Override
3948
public boolean executeInSequence() {
4049
return true;

core/src/com/cloud/agent/api/StartAnswer.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424
import com.cloud.agent.api.to.VirtualMachineTO;
2525

2626
public class StartAnswer extends Answer {
27+
public static final String PATH = "path";
28+
public static final String IMAGE_FORMAT = "imageFormat";
29+
2730
VirtualMachineTO vm;
2831
String hostGuid;
29-
Map<String, String> _iqnToPath;
32+
private Map<String, Map<String, String>> _iqnToData;
3033

3134
protected StartAnswer() {
3235
}
@@ -61,11 +64,11 @@ public String getHost_guid() {
6164
return hostGuid;
6265
}
6366

64-
public void setIqnToPath(Map<String, String> iqnToPath) {
65-
_iqnToPath = iqnToPath;
67+
public void setIqnToData(Map<String, Map<String, String>> iqnToData) {
68+
_iqnToData = iqnToData;
6669
}
6770

68-
public Map<String, String> getIqnToPath() {
69-
return _iqnToPath;
71+
public Map<String, Map<String, String>> getIqnToData() {
72+
return _iqnToData;
7073
}
7174
}

core/src/com/cloud/agent/api/StopCommand.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
import com.cloud.agent.api.to.GPUDeviceTO;
2323
import com.cloud.vm.VirtualMachine;
2424

25+
import java.util.ArrayList;
26+
import java.util.Map;
27+
import java.util.List;
28+
2529
public class StopCommand extends RebootCommand {
2630
private boolean isProxy = false;
2731
private String urlPort = null;
@@ -30,6 +34,11 @@ public class StopCommand extends RebootCommand {
3034
boolean checkBeforeCleanup = false;
3135
String controlIp = null;
3236
boolean forceStop = false;
37+
/**
38+
* On KVM when using iSCSI-based managed storage, if the user shuts a VM down from the guest OS (as opposed to doing so from CloudStack),
39+
* we need to pass to the KVM agent a list of applicable iSCSI volumes that need to be disconnected.
40+
*/
41+
private List<Map<String, String>> volumesToDisconnect = new ArrayList<>();
3342

3443
protected StopCommand() {
3544
}
@@ -102,4 +111,12 @@ public void setControlIp(String controlIp){
102111
public boolean isForceStop() {
103112
return forceStop;
104113
}
114+
115+
public void setVolumesToDisconnect(List<Map<String, String>> volumesToDisconnect) {
116+
this.volumesToDisconnect = volumesToDisconnect;
117+
}
118+
119+
public List<Map<String, String>> getVolumesToDisconnect() {
120+
return volumesToDisconnect;
121+
}
105122
}

0 commit comments

Comments
 (0)