Skip to content

Commit 85a8a80

Browse files
committed
FR562: Flexible cluster migration (#22)
https://shapeblue.atlassian.net/browse/FRO-910
1 parent e53159f commit 85a8a80

File tree

21 files changed

+1349
-569
lines changed

21 files changed

+1349
-569
lines changed

api/src/com/cloud/hypervisor/HypervisorGuru.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
import java.util.List;
2020
import java.util.Map;
2121

22-
import com.cloud.storage.StoragePool;
2322
import org.apache.cloudstack.framework.config.ConfigKey;
2423

2524
import com.cloud.agent.api.Command;
2625
import com.cloud.agent.api.to.NicTO;
2726
import com.cloud.agent.api.to.VirtualMachineTO;
2827
import com.cloud.hypervisor.Hypervisor.HypervisorType;
28+
import com.cloud.storage.StoragePool;
29+
import com.cloud.storage.Volume;
2930
import com.cloud.utils.Pair;
3031
import com.cloud.utils.component.Adapter;
3132
import com.cloud.vm.NicProfile;
@@ -93,5 +94,5 @@ public interface HypervisorGuru extends Adapter {
9394
* @param destination the primary storage pool to migrate to
9495
* @return a list of commands to perform for a successful migration
9596
*/
96-
List<Command> finalizeMigrate(VirtualMachine vm, StoragePool destination);
97+
List<Command> finalizeMigrate(VirtualMachine vm, Map<Volume, StoragePool> volumeToPool);
9798
}

api/src/com/cloud/vm/UserVmService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,8 @@ UserVm moveVMToUser(AssignVMCmd moveUserVMCmd) throws ResourceAllocationExceptio
485485

486486
VirtualMachine vmStorageMigration(Long vmId, StoragePool destPool);
487487

488+
VirtualMachine vmStorageMigration(Long vmId, Map<String, String> volumeToPool);
489+
488490
UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException;
489491

490492
UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,

api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import java.util.Iterator;
2222
import java.util.Map;
2323

24-
import org.apache.log4j.Logger;
25-
2624
import org.apache.cloudstack.api.APICommand;
2725
import org.apache.cloudstack.api.ApiConstants;
2826
import org.apache.cloudstack.api.ApiErrorCode;
@@ -32,6 +30,8 @@
3230
import org.apache.cloudstack.api.ServerApiException;
3331
import org.apache.cloudstack.api.response.HostResponse;
3432
import org.apache.cloudstack.api.response.UserVmResponse;
33+
import org.apache.commons.collections.MapUtils;
34+
import org.apache.log4j.Logger;
3535

3636
import com.cloud.event.EventTypes;
3737
import com.cloud.exception.ConcurrentOperationException;
@@ -61,7 +61,6 @@ public class MigrateVirtualMachineWithVolumeCmd extends BaseAsyncCmd {
6161
@Parameter(name = ApiConstants.HOST_ID,
6262
type = CommandType.UUID,
6363
entityType = HostResponse.class,
64-
required = true,
6564
description = "Destination Host ID to migrate VM to.")
6665
private Long hostId;
6766

@@ -97,7 +96,7 @@ public Long getVirtualMachineId() {
9796

9897
public Map<String, String> getVolumeToPool() {
9998
Map<String, String> volumeToPoolMap = new HashMap<String, String>();
100-
if (migrateVolumeTo != null && !migrateVolumeTo.isEmpty()) {
99+
if (MapUtils.isNotEmpty(migrateVolumeTo)) {
101100
Collection<?> allValues = migrateVolumeTo.values();
102101
Iterator<?> iter = allValues.iterator();
103102
while (iter.hasNext()) {
@@ -141,19 +140,35 @@ public String getEventDescription() {
141140

142141
@Override
143142
public void execute() {
143+
if (hostId == null && MapUtils.isEmpty(migrateVolumeTo)) {
144+
throw new InvalidParameterValueException(String.format("Either %s or %s must be passed for migrating the VM", ApiConstants.HOST_ID, ApiConstants.MIGRATE_TO));
145+
}
146+
144147
UserVm userVm = _userVmService.getUserVm(getVirtualMachineId());
145148
if (userVm == null) {
146149
throw new InvalidParameterValueException("Unable to find the VM by id=" + getVirtualMachineId());
147150
}
148151

149-
Host destinationHost = _resourceService.getHost(getHostId());
150-
// OfflineVmwareMigration: destination host would have to not be a required parameter for stopped VMs
151-
if (destinationHost == null) {
152-
throw new InvalidParameterValueException("Unable to find the host to migrate the VM, host id =" + getHostId());
152+
if (!VirtualMachine.State.Running.equals(userVm.getState()) && hostId != null) {
153+
throw new InvalidParameterValueException(String.format("VM ID: %s is not in Running state to migrate it to new host", userVm.getUuid()));
154+
}
155+
156+
if (!VirtualMachine.State.Stopped.equals(userVm.getState()) && hostId == null) {
157+
throw new InvalidParameterValueException(String.format("VM ID: %s is not in Stopped state to migrate, use %s parameter to migrate it to a new host", userVm.getUuid(), ApiConstants.HOST_ID));
153158
}
154159

155160
try {
156-
VirtualMachine migratedVm = _userVmService.migrateVirtualMachineWithVolume(getVirtualMachineId(), destinationHost, getVolumeToPool());
161+
VirtualMachine migratedVm = null;
162+
if (hostId != null) {
163+
Host destinationHost = _resourceService.getHost(getHostId());
164+
// OfflineVmwareMigration: destination host would have to not be a required parameter for stopped VMs
165+
if (destinationHost == null) {
166+
throw new InvalidParameterValueException("Unable to find the host to migrate the VM, host id =" + getHostId());
167+
}
168+
migratedVm = _userVmService.migrateVirtualMachineWithVolume(getVirtualMachineId(), destinationHost, getVolumeToPool());
169+
} else if (MapUtils.isNotEmpty(migrateVolumeTo)) {
170+
migratedVm = _userVmService.vmStorageMigration(getVirtualMachineId(), getVolumeToPool());
171+
}
157172
if (migratedVm != null) {
158173
UserVmResponse response = _responseGenerator.createUserVmResponse(ResponseView.Full, "virtualmachine", (UserVm)migratedVm).get(0);
159174
response.setResponseName(getCommandName());

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

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,48 +18,50 @@
1818
//
1919
package com.cloud.agent.api;
2020

21-
import com.cloud.agent.api.to.VolumeTO;
21+
import java.util.List;
2222

23-
import java.util.Collection;
23+
import com.cloud.agent.api.to.StorageFilerTO;
24+
import com.cloud.agent.api.to.VolumeTO;
25+
import com.cloud.utils.Pair;
2426

2527
/**
2628
* used to tell the agent to migrate a vm to a different primary storage pool.
2729
* It is for now only implemented on Vmware and is supposed to work irrespective of whether the VM is started or not.
2830
*
2931
*/
3032
public class MigrateVmToPoolCommand extends Command {
31-
private Collection<VolumeTO> volumes;
3233
private String vmName;
33-
private String destinationPool;
3434
private boolean executeInSequence = false;
35+
private List<Pair<VolumeTO, StorageFilerTO>> volumeToFilerAsList;
36+
private String hostGuidInTargetCluster;
3537

3638
protected MigrateVmToPoolCommand() {
3739
}
3840

3941
/**
4042
*
4143
* @param vmName the name of the VM to migrate
42-
* @param volumes used to supply feedback on vmware generated names
43-
* @param destinationPool the primary storage pool to migrate the VM to
44+
* @param volumeToFilerTo the volume to primary storage pool map to migrate the VM to
45+
* @param hostGuidInTargetCluster GUID for host in target cluster when migrating across clusters
4446
* @param executeInSequence
4547
*/
46-
public MigrateVmToPoolCommand(String vmName, Collection<VolumeTO> volumes, String destinationPool, boolean executeInSequence) {
48+
public MigrateVmToPoolCommand(String vmName, List<Pair<VolumeTO, StorageFilerTO>> volumeToFilerTo, String hostGuidInTargetCluster, boolean executeInSequence) {
4749
this.vmName = vmName;
48-
this.volumes = volumes;
49-
this.destinationPool = destinationPool;
50+
this.hostGuidInTargetCluster = hostGuidInTargetCluster;
5051
this.executeInSequence = executeInSequence;
52+
this.volumeToFilerAsList = volumeToFilerTo;
5153
}
5254

53-
public Collection<VolumeTO> getVolumes() {
54-
return volumes;
55+
public String getVmName() {
56+
return vmName;
5557
}
5658

57-
public String getDestinationPool() {
58-
return destinationPool;
59+
public List<Pair<VolumeTO, StorageFilerTO>> getVolumeToFilerAsList() {
60+
return volumeToFilerAsList;
5961
}
6062

61-
public String getVmName() {
62-
return vmName;
63+
public String getHostGuidInTargetCluster() {
64+
return hostGuidInTargetCluster;
6365
}
6466

6567
@Override

core/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public class MigrateVolumeCommand extends Command {
3434
StorageFilerTO sourcePool;
3535
String attachedVmName;
3636
Volume.Type volumeType;
37+
String hostGuidInTargetCluster;
3738

3839
private DataTO srcData;
3940
private DataTO destData;
@@ -67,6 +68,11 @@ public MigrateVolumeCommand(DataTO srcData, DataTO destData, Map<String, String>
6768
setWait(timeout);
6869
}
6970

71+
public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool sourcePool, StoragePool targetPool, String hostGuidInTargetCluster) {
72+
this(volumeId, volumePath, sourcePool, targetPool);
73+
this.hostGuidInTargetCluster = hostGuidInTargetCluster;
74+
}
75+
7076
@Override
7177
public boolean executeInSequence() {
7278
return true;
@@ -119,4 +125,8 @@ public Map<String, String> getDestDetails() {
119125
public int getWaitInMillSeconds() {
120126
return getWait() * 1000;
121127
}
128+
129+
public String getHostGuidInTargetCluster() {
130+
return hostGuidInTargetCluster;
131+
}
122132
}

core/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class VolumeObjectTO implements DataTO {
5151
private Long iopsWriteRate;
5252
private DiskCacheMode cacheMode;
5353
private Hypervisor.HypervisorType hypervisorType;
54+
private String dataStoreUuid;
5455

5556
public VolumeObjectTO() {
5657

@@ -252,4 +253,12 @@ public void setCacheMode(DiskCacheMode cacheMode) {
252253
public DiskCacheMode getCacheMode() {
253254
return cacheMode;
254255
}
256+
257+
public String getDataStoreUuid() {
258+
return dataStoreUuid;
259+
}
260+
261+
public void setDataStoreUuid(String dataStoreUuid) {
262+
this.dataStoreUuid = dataStoreUuid;
263+
}
255264
}

engine/api/src/com/cloud/vm/VirtualMachineManager.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import com.cloud.offering.DiskOffering;
4040
import com.cloud.offering.DiskOfferingInfo;
4141
import com.cloud.offering.ServiceOffering;
42-
import com.cloud.storage.StoragePool;
4342
import com.cloud.template.VirtualMachineTemplate;
4443
import com.cloud.utils.component.Manager;
4544
import com.cloud.utils.fsm.NoTransitionException;
@@ -139,7 +138,7 @@ void advanceReboot(String vmUuid, Map<VirtualMachineProfile.Param, Object> param
139138

140139
VirtualMachine findById(long vmId);
141140

142-
void storageMigration(String vmUuid, StoragePool storagePoolId);
141+
void storageMigration(String vmUuid, Map<Long, Long> volumeToPool);
143142

144143
/**
145144
* @param vmInstance

engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Lon
107107

108108
void migrateVolumes(VirtualMachine vm, VirtualMachineTO vmTo, Host srcHost, Host destHost, Map<Volume, StoragePool> volumeToPool);
109109

110-
boolean storageMigration(VirtualMachineProfile vm, StoragePool destPool) throws StorageUnavailableException;
110+
boolean storageMigration(VirtualMachineProfile vm, Map<Volume, StoragePool> volumeToPool) throws StorageUnavailableException;
111111

112112
void prepareForMigration(VirtualMachineProfile vm, DeployDestination dest);
113113

0 commit comments

Comments
 (0)