vmware: improve support for disk controllers

- Improve disk chain usage while attaching, migrating disks
- Gets root disk controller based diskDeviceBusName from volume's chain info

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2016-01-25 17:56:01 +01:00
parent dd2d8867a9
commit b6a6add9b7
8 changed files with 131 additions and 0 deletions

View File

@ -24,6 +24,7 @@ import com.cloud.agent.api.Command;
public class MigrateVolumeAnswer extends Answer {
private String volumePath;
private String volumeChain;
public MigrateVolumeAnswer(Command command, boolean success, String details, String volumePath) {
super(command, success, details);
@ -38,4 +39,12 @@ public class MigrateVolumeAnswer extends Answer {
public String getVolumePath() {
return volumePath;
}
public String getVolumeChainInfo() {
return volumeChain;
}
public void setVolumeChainInfo(String volumeChain) {
this.volumeChain = volumeChain;
}
}

View File

@ -22,8 +22,11 @@ package org.apache.cloudstack.storage.command;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.DiskTO;
import java.util.Map;
public class AttachAnswer extends Answer {
private DiskTO disk;
private Map<String, String> diskDetails;
public AttachAnswer() {
super(null);
@ -34,6 +37,12 @@ public class AttachAnswer extends Answer {
setDisk(disk);
}
public AttachAnswer(DiskTO disk, Map<String, String> diskDetails) {
super(null);
setDisk(disk);
setDiskDetails(diskDetails);
}
public AttachAnswer(String errMsg) {
super(null, false, errMsg);
}
@ -45,4 +54,12 @@ public class AttachAnswer extends Answer {
public void setDisk(DiskTO disk) {
this.disk = disk;
}
public Map<String, String> getDiskDetails() {
return diskDetails;
}
public void setDiskDetails(Map<String, String> diskDetails) {
this.diskDetails = diskDetails;
}
}

View File

@ -407,6 +407,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
VolumeVO volumeVo = volDao.findById(volume.getId());
Long oldPoolId = volume.getPoolId();
volumeVo.setPath(((MigrateVolumeAnswer)answer).getVolumePath());
String chainInfo = ((MigrateVolumeAnswer) answer).getVolumeChainInfo();
if (chainInfo != null) {
volumeVo.setChainInfo(chainInfo);
}
volumeVo.setPodId(destPool.getPodId());
volumeVo.setPoolId(destPool.getId());
volumeVo.setLastPoolId(oldPoolId);

View File

@ -207,6 +207,9 @@ public class VmwareStorageMotionStrategy implements DataMotionStrategy {
VolumeVO volumeVO = volDao.findById(volume.getId());
Long oldPoolId = volumeVO.getPoolId();
volumeVO.setPath(volumeTo.getPath());
if (volumeTo.getChainInfo() != null) {
volumeVO.setChainInfo(volumeTo.getChainInfo());
}
volumeVO.setLastPoolId(oldPoolId);
volumeVO.setFolder(pool.getPath());
volumeVO.setPodId(pool.getPodId());

View File

@ -26,6 +26,7 @@ import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
import org.apache.cloudstack.utils.volume.VirtualMachineVolumeChainInfo;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
@ -96,16 +97,19 @@ import com.cloud.exception.StorageUnavailableException;
import com.cloud.gpu.GPU;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.HypervisorCapabilitiesVO;
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
import com.cloud.org.Grouping;
import com.cloud.serializer.GsonHelper;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeDetailsDao;
import com.cloud.storage.snapshot.SnapshotApiService;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.template.TemplateManager;
@ -134,6 +138,7 @@ import com.cloud.utils.db.UUIDManager;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
@ -154,6 +159,8 @@ import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiService, VmWorkJobHandler {
private final static Logger s_logger = Logger.getLogger(VolumeApiServiceImpl.class);
@ -176,6 +183,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
@Inject
VolumeDao _volsDao;
@Inject
VolumeDetailsDao _volDetailDao;
@Inject
HostDao _hostDao;
@Inject
SnapshotDao _snapshotDao;
@ -225,6 +234,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
VmWorkJobDao _workJobDao;
@Inject
ClusterDetailsDao _clusterDetailsDao;
@Inject
UserVmManager _userVmMgr;
protected Gson _gson;
private List<StoragePoolAllocator> _storagePoolAllocators;
@ -238,6 +250,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
protected VolumeApiServiceImpl() {
_volStateMachine = Volume.State.getStateMachine();
_gson = GsonHelper.getGsonLogger();
}
/*
@ -1781,6 +1794,23 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
throw new InvalidParameterValueException("Cannot migrate ROOT volume of a stopped VM to a storage pool in a different VMware datacenter");
}
}
String rootVolChainInfo = vol.getChainInfo();
if ((vm.getType().equals(VirtualMachine.Type.User)) && (rootVolChainInfo != null) && (!rootVolChainInfo.isEmpty())) {
String rootDiskController = null;
try {
VirtualMachineVolumeChainInfo infoInChain = _gson.fromJson(rootVolChainInfo, VirtualMachineVolumeChainInfo.class);
if (infoInChain != null) {
rootDiskController = infoInChain.getControllerFromDeviceBusName();
}
UserVmVO userVmVo = _userVmDao.findById(vm.getId());
if ((rootDiskController != null) && (!rootDiskController.isEmpty())) {
_userVmDao.loadDetails(userVmVo);
_userVmMgr.persistDeviceBusInfo(userVmVo, rootDiskController);
}
} catch (JsonParseException ignored) {
}
}
}
}
}
@ -2349,6 +2379,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
_volsDao.update(volumeToAttach.getId(), volumeToAttach);
}
if (host.getHypervisorType() == Hypervisor.HypervisorType.VMware) {
Map<String, String> diskDetails = answer.getDiskDetails();
for (Map.Entry<String, String> detail : diskDetails.entrySet()) {
VolumeDetailVO volumeDetailVo = new VolumeDetailVO(volumeToAttach.getId(), detail.getKey(), detail.getValue(), true);
_volDetailDao.persist(volumeDetailVo);
}
}
} else {
_volsDao.attachVolume(volumeToAttach.getId(), vm.getId(), deviceId);
}

View File

@ -111,4 +111,6 @@ public interface UserVmManager extends UserVmService {
public void removeCustomOfferingDetails(long vmId);
void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType);
void persistDeviceBusInfo(UserVmVO paramUserVmVO, String paramString);
}

View File

@ -5028,6 +5028,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
}
public void persistDeviceBusInfo(UserVmVO vm, String rootDiskController) {
String existingVmRootDiskController = vm.getDetail(VmDetailConstants.ROOK_DISK_CONTROLLER);
if (((existingVmRootDiskController == null) || (existingVmRootDiskController.isEmpty())) && (rootDiskController != null) && (!rootDiskController.isEmpty())) {
vm.setDetail(VmDetailConstants.ROOK_DISK_CONTROLLER, rootDiskController);
_vmDao.saveDetails(vm);
s_logger.debug("Persisted device bus information rootDiskController=" + rootDiskController + " for vm: " + vm.getDisplayName());
}
}
@Override
public String getConfigComponentName() {
return UserVmManager.class.getSimpleName();

View File

@ -0,0 +1,48 @@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
package org.apache.cloudstack.utils.volume;
public class VirtualMachineVolumeChainInfo {
String diskDeviceBusName;
String[] diskChain;
public String getDiskDeviceBusName() {
return this.diskDeviceBusName;
}
public void setDiskDeviceBusName(String diskDeviceBusName) {
this.diskDeviceBusName = diskDeviceBusName;
}
public String[] getDiskChain() {
return this.diskChain;
}
public void setDiskChain(String[] diskChain) {
this.diskChain = diskChain;
}
public String getControllerFromDeviceBusName() {
if ((this.diskDeviceBusName == null) || (this.diskDeviceBusName.isEmpty()) || (!this.diskDeviceBusName.contains(":"))) {
return null;
}
return this.diskDeviceBusName.substring(0, this.diskDeviceBusName.indexOf(":") - 1);
}
}