Skip to content

Commit 3cbac98

Browse files
DaanHooglandnvazquez
authored andcommitted
Offline volume migrations for Vmware (#6)
* [CLOUDSTACK-9858] Retirement of midonet plugin (build disabling) * build problem workaround for conflicting java versions * research comments * Adding marvin tests for: 1) simple VM migration with root volume 2) migration of vm and volume for a vm with 2 data disks 3) volume migration of detached disk * the hypervisor-guru made migrate aware implemented for vmware * enable canHandle and implement detached volume migration for vmware * rename method to fit naming scheme * command rename to better specify scope of action * pull up condition for readability * extract some logic for readability * fixing the migrate detached volume test * info on destination cluster * extra attempts on volume paths * logging on name not found * move volume to root after migration * vmdk-extension * nuage profile readded * defensive debug logging * Fix tag matching in 'migrateVolume'` * Fix was meant for disk offering replacement and addapted for regular migration * tagging tests * reset status on failure * Revert "nuage profile readded" This reverts commit 05664c1801163ae2959052fa88cb87303ad93972. * limit migration jobs * null pointers during startup * old style config * space * job count method * job count check * implement global setting fixes Signed-off-by: Rohit Yadav <[email protected]> * option2: implement throwing exception if async_job table pending jobs exceed the threshold for migration Signed-off-by: Rohit Yadav <[email protected]> * option1: use the sync_queue mechanism to limit execution per DS This uses the ideal way that must be accepted by the community that uses the sync_queue + the global setting via API dispatcher to enforce the number of async API jobs executed for a sync Obj ID (datastore in our cases). This is much cleaner implementation but involves changes to the job framework, in case of any regressions we'll partially revert this commit and aim to fix this during community submission. Signed-off-by: Rohit Yadav <[email protected]> * revert option2 - removes check/exception way We can re-revert this commit to get the changes back Signed-off-by: Rohit Yadav <[email protected]> * Revert "option1: use the sync_queue mechanism to limit execution per DS" This reverts commit c4c286c5ac87171018b99fb079e512477fcb0aa0. * Revert "revert option2 - removes check/exception way" This reverts commit c610f476ddc9f42ab7e6f7a799c1b825cf96ae99.
1 parent b011402 commit 3cbac98

File tree

55 files changed

+1681
-3141
lines changed

Some content is hidden

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

55 files changed

+1681
-3141
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.List;
2020
import java.util.Map;
2121

22+
import com.cloud.storage.StoragePool;
2223
import org.apache.cloudstack.framework.config.ConfigKey;
2324

2425
import com.cloud.agent.api.Command;
@@ -84,4 +85,13 @@ public interface HypervisorGuru extends Adapter {
8485
List<Command> finalizeExpungeVolumes(VirtualMachine vm);
8586

8687
Map<String, String> getClusterSettings(long vmId);
88+
89+
/**
90+
* will generate commands to migrate a vm to a pool. For now this will ony work for stopped VMs on Vmware.
91+
*
92+
* @param vm the stopped vm to migrate
93+
* @param destination the primary storage pool to migrate to
94+
* @return a list of commands to perform for a succesful migration
95+
*/
96+
List<Command> finalizeMigrate(VirtualMachine vm, StoragePool destination);
8797
}

api/src/com/cloud/storage/VolumeApiService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,16 @@
3131
import com.cloud.exception.ResourceAllocationException;
3232
import com.cloud.user.Account;
3333
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
34+
import org.apache.cloudstack.framework.config.ConfigKey;
3435

3536
import java.net.MalformedURLException;
3637

3738
public interface VolumeApiService {
39+
ConfigKey<Long> ConcurrentMigrationsThresholdPerDatastore = new ConfigKey<Long>("Advanced", Long.class,
40+
"concurrent.migrations.per.target.datastore", "0",
41+
"Limits number of migrations that can be handled per target datastore concurrently. Default is 0 - unlimited.",
42+
true, ConfigKey.Scope.Global);
43+
3844
/**
3945
* Creates the database object for a volume based on the given criteria
4046
*

api/src/org/apache/cloudstack/api/BaseAsyncCmd.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public abstract class BaseAsyncCmd extends BaseCmd {
2727
public static final String ipAddressSyncObject = "ipaddress";
2828
public static final String networkSyncObject = "network";
2929
public static final String vpcSyncObject = "vpc";
30+
public static final String migrationSyncObject = "migration";
3031
public static final String snapshotHostSyncObject = "snapshothost";
3132
public static final String gslbSyncObject = "globalserverloadbalancer";
3233
private static final Logger s_logger = Logger.getLogger(BaseAsyncCmd.class.getName());

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,25 @@ public void execute() {
186186
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
187187
}
188188
}
189+
190+
@Override
191+
public String getSyncObjType() {
192+
if (getSyncObjId() != null) {
193+
return BaseAsyncCmd.migrationSyncObject;
194+
}
195+
return null;
196+
}
197+
198+
@Override
199+
public Long getSyncObjId() {
200+
if (getStoragePoolId() != null) {
201+
return getStoragePoolId();
202+
}
203+
// OfflineVmwareMigrations: undocumented feature;
204+
// OfflineVmwareMigrations: on implementing a maximum queue size for per storage migrations it seems counter intuitive for the user to not enforce it for hosts as well.
205+
if (getHostId() != null) {
206+
return getHostId();
207+
}
208+
return null;
209+
}
189210
}

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ public void execute() {
147147
}
148148

149149
Host destinationHost = _resourceService.getHost(getHostId());
150+
// OfflineVmwareMigration: destination host would have to not be a required parameter for stopped VMs
150151
if (destinationHost == null) {
151152
throw new InvalidParameterValueException("Unable to find the host to migrate the VM, host id =" + getHostId());
152153
}
@@ -163,13 +164,7 @@ public void execute() {
163164
} catch (ResourceUnavailableException ex) {
164165
s_logger.warn("Exception: ", ex);
165166
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
166-
} catch (ConcurrentOperationException e) {
167-
s_logger.warn("Exception: ", e);
168-
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
169-
} catch (ManagementServerException e) {
170-
s_logger.warn("Exception: ", e);
171-
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
172-
} catch (VirtualMachineMigrationException e) {
167+
} catch (ConcurrentOperationException | ManagementServerException | VirtualMachineMigrationException e) {
173168
s_logger.warn("Exception: ", e);
174169
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
175170
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,19 @@ public void execute() {
119119
}
120120
}
121121

122+
@Override
123+
public String getSyncObjType() {
124+
if (getSyncObjId() != null) {
125+
return BaseAsyncCmd.migrationSyncObject;
126+
}
127+
return null;
128+
}
129+
130+
@Override
131+
public Long getSyncObjId() {
132+
if (getStoragePoolId() != null) {
133+
return getStoragePoolId();
134+
}
135+
return null;
136+
}
122137
}

client/pom.xml

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,6 @@
136136
<artifactId>cloud-plugin-network-bigswitch</artifactId>
137137
<version>${project.version}</version>
138138
</dependency>
139-
<dependency>
140-
<groupId>org.apache.cloudstack</groupId>
141-
<artifactId>cloud-plugin-network-midonet</artifactId>
142-
<version>${project.version}</version>
143-
</dependency>
144139
<dependency>
145140
<groupId>org.apache.cloudstack</groupId>
146141
<artifactId>cloud-plugin-network-ssp</artifactId>
@@ -995,21 +990,6 @@
995990
</dependency>
996991
</dependencies>
997992
</profile>
998-
<profile>
999-
<id>nuagevsp</id>
1000-
<activation>
1001-
<property>
1002-
<name>noredist</name>
1003-
</property>
1004-
</activation>
1005-
<dependencies>
1006-
<dependency>
1007-
<groupId>org.apache.cloudstack</groupId>
1008-
<artifactId>cloud-plugin-network-vsp</artifactId>
1009-
<version>${project.version}</version>
1010-
</dependency>
1011-
</dependencies>
1012-
</profile>
1013993
<profile>
1014994
<id>srx</id>
1015995
<activation>

core/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@
134134
<bean id="ipDeployersRegistry"
135135
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
136136
<property name="excludeKey" value="ip.deployers.exclude" />
137-
<property name="excludeDefault" value="MidoNetElement" />
138137
<property name="preRegistered">
139138
<list>
140139
<ref bean="VpcVirtualRouter" />
@@ -145,7 +144,6 @@
145144
<bean id="dhcpProvidersRegistry"
146145
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
147146
<property name="excludeKey" value="dhcp.providers.exclude" />
148-
<property name="excludeDefault" value="MidoNetElement" />
149147
<property name="preRegistered">
150148
<list>
151149
<ref bean="VpcVirtualRouter" />
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
20+
package com.cloud.agent.api;
21+
22+
import org.apache.cloudstack.storage.to.VolumeObjectTO;
23+
24+
import java.util.List;
25+
26+
public class MigrateVmToPoolAnswer extends Answer {
27+
28+
List<VolumeObjectTO> volumeTos;
29+
30+
public MigrateVmToPoolAnswer(MigrateVmToPoolCommand cmd, Exception ex) {
31+
super(cmd, ex);
32+
volumeTos = null;
33+
}
34+
35+
public MigrateVmToPoolAnswer(MigrateVmToPoolCommand cmd, List<VolumeObjectTO> volumeTos) {
36+
super(cmd, true, null);
37+
this.volumeTos = volumeTos;
38+
}
39+
40+
public List<VolumeObjectTO> getVolumeTos() {
41+
return volumeTos;
42+
}
43+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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 com.cloud.agent.api;
20+
21+
import com.cloud.agent.api.to.VolumeTO;
22+
23+
import java.util.Collection;
24+
25+
/**
26+
* used to tell the agent to migrate a vm to a different primare storage pool.
27+
* It is for now only mplemented on Vmware and is supposed to work irrespective of whether the VM is started or not.
28+
*
29+
*/
30+
public class MigrateVmToPoolCommand extends Command {
31+
private Collection<VolumeTO> volumes;
32+
private String vmName;
33+
private String destinationPool;
34+
private boolean executeInSequence = false;
35+
36+
protected MigrateVmToPoolCommand() {
37+
}
38+
39+
/**
40+
*
41+
* @param vmName the name of the VM to migrate
42+
* @param volumes used to suplly feedback on vmware generated names
43+
* @param destinationPool the primare storage pool to migrate the VM to
44+
* @param executeInSequence
45+
*/
46+
public MigrateVmToPoolCommand(String vmName, Collection<VolumeTO> volumes, String destinationPool, boolean executeInSequence) {
47+
this.vmName = vmName;
48+
this.volumes = volumes;
49+
this.destinationPool = destinationPool;
50+
this.executeInSequence = executeInSequence;
51+
}
52+
53+
public Collection<VolumeTO> getVolumes() {
54+
return volumes;
55+
}
56+
57+
public String getDestinationPool() {
58+
return destinationPool;
59+
}
60+
61+
public String getVmName() {
62+
return vmName;
63+
}
64+
65+
@Override
66+
public boolean executeInSequence() {
67+
return executeInSequence;
68+
}
69+
70+
}

0 commit comments

Comments
 (0)