Skip to content

Commit deb694c

Browse files
author
Jayapal
committed
CLOUDSTACK-8324: Added migration changes for config drive
1 parent 469d9eb commit deb694c

8 files changed

Lines changed: 337 additions & 12 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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 java.util.List;
23+
24+
public class AttachOrDettachConfigDriveCommand extends Command {
25+
26+
String vmName;
27+
List<String[]> vmData;
28+
String configDriveLabel;
29+
boolean isAttach = false;
30+
31+
public AttachOrDettachConfigDriveCommand(String vmName, List<String[]> vmData, String label, boolean attach) {
32+
this.vmName = vmName;
33+
this.vmData = vmData;
34+
this.configDriveLabel = label;
35+
this.isAttach = attach;
36+
}
37+
38+
@Override
39+
public boolean executeInSequence() {
40+
return false;
41+
}
42+
43+
public String getVmName() {
44+
return vmName;
45+
}
46+
47+
public List<String[]> getVmData() {
48+
return vmData;
49+
}
50+
51+
public boolean isAttach() {
52+
return isAttach;
53+
}
54+
55+
public String getConfigDriveLabel() {
56+
return configDriveLabel;
57+
}
58+
}

engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import javax.inject.Inject;
3939
import javax.naming.ConfigurationException;
4040

41+
import com.cloud.agent.api.AttachOrDettachConfigDriveCommand;
4142
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
4243
import org.apache.cloudstack.context.CallContext;
4344
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@@ -273,6 +274,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
273274
protected VGPUTypesDao _vgpuTypesDao;
274275
@Inject
275276
protected EntityManager _entityMgr;
277+
@Inject
278+
protected GuestOSCategoryDao _guestOSCategoryDao;
279+
@Inject
280+
protected GuestOSDao _guestOSDao = null;
281+
@Inject
282+
protected UserVmDetailsDao _vmDetailsDao;
283+
@Inject
284+
ServiceOfferingDao _serviceOfferingDao = null;
276285

277286
@Inject
278287
ConfigDepot _configDepot;
@@ -315,6 +324,8 @@ public void setHostAllocators(final List<HostAllocator> hostAllocators) {
315324
protected VmWorkJobDao _workJobDao;
316325
@Inject
317326
protected AsyncJobManager _jobMgr;
327+
@Inject
328+
protected UserVmService _userVmSrv;
318329

319330
VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
320331

@@ -352,6 +363,9 @@ public void setHostAllocators(final List<HostAllocator> hostAllocators) {
352363
Integer.class, "vm.job.report.interval", "60",
353364
"Interval to send application level pings to make sure the connection is still working", false);
354365

366+
static final ConfigKey<String> VmConfigDriveLabel = new ConfigKey<String>("Hidden", String.class, "vm.configdrive.label", "config",
367+
"The default lable name for the config drive", false);
368+
355369
ScheduledExecutorService _executor = null;
356370

357371
protected long _nodeId;
@@ -1916,6 +1930,7 @@ protected void migrate(final VMInstanceVO vm, final long srcHostId, final Deploy
19161930
final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, null, _offeringDao.findById(vm.getId(), vm.getServiceOfferingId()), null, null);
19171931
_networkMgr.prepareNicForMigration(profile, dest);
19181932
volumeMgr.prepareForMigration(profile, dest);
1933+
profile.setConfigDriveLabel( _userVmSrv.VmConfigDriveLabel.value());
19191934

19201935
final VirtualMachineTO to = toVmTO(profile);
19211936
final PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
@@ -2215,6 +2230,48 @@ private void orchestrateMigrateWithStorage(final String vmUuid, final long srcHo
22152230

22162231
boolean migrated = false;
22172232
try {
2233+
2234+
// config drive: Detach the config drive at source host
2235+
// After migration successful attach the config drive in destination host
2236+
// On migration failure VM will be stopped, So configIso will be deleted
2237+
2238+
Nic defaultNic = _networkModel.getDefaultNic(vm.getId());
2239+
2240+
List<String[]> vmData = null;
2241+
if (defaultNic != null) {
2242+
UserVmVO userVm = _userVmDao.findById(vm.getId());
2243+
Map<String, String> details = _vmDetailsDao.listDetailsKeyPairs(vm.getId());
2244+
vm.setDetails(details);
2245+
2246+
Network network = _networkModel.getNetwork(defaultNic.getNetworkId());
2247+
if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
2248+
final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
2249+
final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
2250+
boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
2251+
2252+
vmData = _networkModel.generateVmData(userVm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
2253+
(String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
2254+
String vmName = vm.getInstanceName();
2255+
String configDriveIsoRootFolder = "/tmp";
2256+
String isoFile = configDriveIsoRootFolder + "/" + vmName + "/configDrive/" + vmName + ".iso";
2257+
profile.setVmData(vmData);
2258+
profile.setConfigDriveLabel(VmConfigDriveLabel.value());
2259+
profile.setConfigDriveIsoRootFolder(configDriveIsoRootFolder);
2260+
profile.setConfigDriveIsoFile(isoFile);
2261+
2262+
// At source host detach the config drive iso.
2263+
AttachOrDettachConfigDriveCommand dettachCommand = new AttachOrDettachConfigDriveCommand(vm.getInstanceName(), vmData, VmConfigDriveLabel.value(), false);
2264+
try {
2265+
_agentMgr.send(srcHost.getId(), dettachCommand);
2266+
s_logger.debug("Deleted config drive ISO for vm " + vm.getInstanceName() + " In host " + srcHost);
2267+
} catch (OperationTimedoutException e) {
2268+
s_logger.debug("TIme out occured while exeuting command AttachOrDettachConfigDrive " + e.getMessage());
2269+
2270+
}
2271+
2272+
}
2273+
}
2274+
22182275
// Migrate the vm and its volume.
22192276
volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPoolMap);
22202277

@@ -3614,7 +3671,7 @@ public String getConfigComponentName() {
36143671
public ConfigKey<?>[] getConfigKeys() {
36153672
return new ConfigKey<?>[] {ClusterDeltaSyncInterval, StartRetry, VmDestroyForcestop, VmOpCancelInterval, VmOpCleanupInterval, VmOpCleanupWait,
36163673
VmOpLockStateRetry,
3617-
VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval};
3674+
VmOpWaitInterval, ExecuteInSequence, VmJobCheckInterval, VmJobTimeout, VmJobStateReportInterval, VmConfigDriveLabel};
36183675
}
36193676

36203677
public List<StoragePoolAllocator> getStoragePoolAllocators() {

plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ private static boolean isAlienVm(final VM vm, final Connection conn) throws XenA
258258

259259
protected String _configDriveIsopath = "/opt/xensource/packages/configdrive_iso/";
260260
protected String _configDriveSRName = "ConfigDriveISOs";
261-
protected String _attachIsoDeviceNum = "3";
261+
public String _attachIsoDeviceNum = "3";
262262

263263
protected XenServerUtilitiesHelper xenServerUtilitiesHelper = new XenServerUtilitiesHelper();
264264

@@ -3908,17 +3908,29 @@ public ExecutionResult prepareCommand(final NetworkElementCommand cmd) {
39083908
return new ExecutionResult(true, null);
39093909
}
39103910

3911-
public void prepareISO(final Connection conn, final String vmName) throws XmlRpcException, XenAPIException {
3911+
public void prepareISO(final Connection conn, final String vmName, List<String[]> vmDataList, String configDriveLabel) throws XmlRpcException, XenAPIException {
39123912

39133913
final Set<VM> vms = VM.getByNameLabel(conn, vmName);
39143914
if (vms == null || vms.size() != 1) {
39153915
throw new CloudRuntimeException("There are " + (vms == null ? "0" : vms.size()) + " VMs named " + vmName);
39163916
}
39173917
final VM vm = vms.iterator().next();
3918+
3919+
if (vmDataList != null) {
3920+
// create SR
3921+
SR sr = createLocalIsoSR(conn, _configDriveSRName+getHost().getIp());
3922+
3923+
// 1. create vm data files
3924+
createVmdataFiles(vmName, vmDataList, configDriveLabel);
3925+
3926+
// 2. copy config drive iso to host
3927+
copyConfigDriveIsoToHost(conn, sr, vmName);
3928+
}
3929+
39183930
final Set<VBD> vbds = vm.getVBDs(conn);
39193931
for (final VBD vbd : vbds) {
39203932
final VBD.Record vbdr = vbd.getRecord(conn);
3921-
if (vbdr.type == Types.VbdType.CD && vbdr.empty == false) {
3933+
if (vbdr.type == Types.VbdType.CD && vbdr.empty == false && vbdr.userdevice.equals(_attachIsoDeviceNum)) {
39223934
final VDI vdi = vbdr.VDI;
39233935
final SR sr = vdi.getSR(conn);
39243936
final Set<PBD> pbds = sr.getPBDs(conn);
@@ -5288,4 +5300,86 @@ public void deleteLocalFolder(final String directory) throws Exception {
52885300
}
52895301
}
52905302

5303+
protected SR getSRByNameLabel(Connection conn, String name) throws BadServerResponse, XenAPIException, XmlRpcException {
5304+
Set<SR> srs = SR.getByNameLabel(conn, name);
5305+
SR ressr = null;
5306+
for (SR sr : srs) {
5307+
Set<PBD> pbds;
5308+
pbds = sr.getPBDs(conn);
5309+
for (PBD pbd : pbds) {
5310+
PBD.Record pbdr = pbd.getRecord(conn);
5311+
if (pbdr.host != null) {
5312+
ressr = sr;
5313+
break;
5314+
}
5315+
}
5316+
}
5317+
return ressr;
5318+
}
5319+
5320+
5321+
public boolean AttachConfigDriveToMigratedVm(Connection conn, String vmName, String ipAddr) {
5322+
5323+
// attach the config drive in destination host
5324+
5325+
try {
5326+
s_logger.debug("Attaching config drive iso device for the VM "+ vmName + " In host "+ ipAddr);
5327+
Set<VM> vms = VM.getByNameLabel(conn, vmName);
5328+
5329+
SR sr = getSRByNameLabel(conn, _configDriveSRName + ipAddr);
5330+
//Here you will find only two vdis with the <vmname>.iso.
5331+
//one is from source host and second from dest host
5332+
Set<VDI> vdis = VDI.getByNameLabel(conn, vmName + ".iso");
5333+
if (vdis.isEmpty()) {
5334+
s_logger.debug("Could not find config drive ISO: " + vmName);
5335+
return false;
5336+
}
5337+
5338+
VDI configdriveVdi = null;
5339+
for (VDI vdi : vdis) {
5340+
SR vdiSr = vdi.getSR(conn);
5341+
if (vdiSr.getUuid(conn).equals(sr.getUuid(conn))) {
5342+
//get this vdi to attach to vbd
5343+
configdriveVdi = vdi;
5344+
s_logger.debug("VDI for the config drive ISO " + vdi);
5345+
} else {
5346+
// delete the vdi in source host so that the <vmname>.iso file is get removed
5347+
s_logger.debug("Removing the source host VDI for the config drive ISO " + vdi);
5348+
vdi.destroy(conn);
5349+
}
5350+
}
5351+
5352+
if (configdriveVdi == null) {
5353+
s_logger.debug("Config drive ISO VDI is not found ");
5354+
return false;
5355+
}
5356+
5357+
for (VM vm : vms) {
5358+
5359+
//create vbd
5360+
VBD.Record cfgDriveVbdr = new VBD.Record();
5361+
cfgDriveVbdr.VM = vm;
5362+
cfgDriveVbdr.empty = true;
5363+
cfgDriveVbdr.bootable = false;
5364+
cfgDriveVbdr.userdevice = "autodetect";
5365+
cfgDriveVbdr.mode = Types.VbdMode.RO;
5366+
cfgDriveVbdr.type = Types.VbdType.CD;
5367+
5368+
VBD cfgDriveVBD = VBD.create(conn, cfgDriveVbdr);
5369+
5370+
s_logger.debug("Inserting vbd " + configdriveVdi);
5371+
cfgDriveVBD.insert(conn, configdriveVdi);
5372+
break;
5373+
5374+
}
5375+
5376+
return true;
5377+
5378+
}catch (Exception ex) {
5379+
s_logger.debug("Failed to attach config drive ISO to the VM "+ vmName + " In host " + ipAddr );
5380+
return false;
5381+
}
5382+
5383+
}
5384+
52915385
}

plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageCommandWrapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public Answer execute(final MigrateWithStorageCommand command, final XenServer61
6767
final XsHost xsHost = xenServer610Resource.getHost();
6868
final String uuid = xsHost.getUuid();
6969
try {
70-
xenServer610Resource.prepareISO(connection, vmName);
70+
xenServer610Resource.prepareISO(connection, vmName, null, null);
7171

7272
// Get the list of networks and recreate VLAN, if required.
7373
for (final NicTO nicTo : vmSpec.getNics()) {

0 commit comments

Comments
 (0)