VMware changes related to managed storage

This commit is contained in:
Mike Tutkowski 2013-10-31 08:27:30 -06:00
parent a3cec3802c
commit 449b5daa70
7 changed files with 147 additions and 13 deletions

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.hypervisor.vmware.manager;
import java.util.List;
import com.cloud.agent.api.Command;
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
@ -33,4 +35,5 @@ public interface VmwareHostService {
String iqn, String initiatorChapName, String initiatorChapSecret, String mutualChapName, String mutualChapSecret) throws Exception;
void createVmdk(Command cmd, DatastoreMO dsMo, String volumeDatastorePath, Long volumeSize) throws Exception;
void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception;
void removeManagedTargetsFromCluster(List<String> managedIqns) throws Exception;
}

View File

@ -2985,7 +2985,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
Map<String, String> details = vol.getDetails();
boolean isManaged = details != null && Boolean.parseBoolean(details.get(DiskTO.MANAGED));
Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid());
if(volumeDsDetails == null)
throw new Exception("Primary datastore " + primaryStore.getUuid() + " is not mounted on host.");
@ -2997,17 +2999,25 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String disks[] = diskInfo.getDiskChain();
for(int i = 0; i < disks.length; i++) {
DatastoreFile file = new DatastoreFile(disks[i]);
if(file.getDir() != null && file.getDir().isEmpty()) {
if (!isManaged && file.getDir() != null && file.getDir().isEmpty()) {
s_logger.info("Perform run-time datastore folder upgrade. sync " + disks[i] + " to VM folder");
disks[i] = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(
dcMo, vmMo.getName(), dsMo, file.getFileBaseName());
}
}
return disks;
}
String datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(
dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
}
final String datastoreDiskPath;
if (isManaged) {
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
}
else {
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(
dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
}
if(!dsMo.fileExists(datastoreDiskPath)) {
s_logger.warn("Volume " + volumeTO.getId() + " does not seem to exist on datastore, out of sync? path: " + datastoreDiskPath);
}
@ -3223,7 +3233,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if(diskInfoBuilder != null) {
VolumeObjectTO volume = (VolumeObjectTO)vol.getData();
VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(volume.getPath());
Map<String, String> details = vol.getDetails();
boolean isManaged = details != null && Boolean.parseBoolean(details.get(DiskTO.MANAGED));
VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(isManaged ? new DatastoreFile(volume.getPath()).getFileBaseName() : volume.getPath());
if(diskInfo != null) {
s_logger.info("Found existing disk info from volume path: " + volume.getPath());
return diskInfo;
@ -3421,7 +3434,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
String poolUuid = primaryStore.getUuid();
if(poolMors.get(poolUuid) == null) {
ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid);
boolean isManaged = false;
String iScsiName = null;
Map<String, String> details = vol.getDetails();
if (details != null) {
isManaged = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
iScsiName = details.get(DiskTO.IQN);
}
ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(iScsiName) : poolUuid);
if (morDataStore == null) {
String msg = "Failed to get the mounted datastore for the volume's pool " + poolUuid;
s_logger.error(msg);
@ -4534,7 +4556,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName());
if (!dsMo.fileExists(volumeDatastorePath)) {
createVmdk(cmd, dsMo, VmwareResource.getDatastoreName(cmd.get_iScsiName()), cmd.getVolumeSize());
createVmdk(cmd, dsMo, volumeDatastorePath, cmd.getVolumeSize());
}
}
else {
@ -4592,6 +4614,35 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
@Override
public void removeManagedTargetsFromCluster(List<String> iqns) throws Exception {
List<HostInternetScsiHbaStaticTarget> lstManagedTargets = new ArrayList<HostInternetScsiHbaStaticTarget>();
VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context);
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
ClusterMO cluster = new ClusterMO(context, morCluster);
List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts();
HostMO host = new HostMO(context, lstHosts.get(0).first());
HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) {
if (hba instanceof HostInternetScsiHba) {
List<HostInternetScsiHbaStaticTarget> lstTargets = ((HostInternetScsiHba)hba).getConfiguredStaticTarget();
if (lstTargets != null) {
for (HostInternetScsiHbaStaticTarget target : lstTargets) {
if (iqns.contains(target.getIScsiName())) {
lstManagedTargets.add(target);
}
}
}
}
}
addRemoveInternetScsiTargetsToAllHosts(false, lstManagedTargets, lstHosts);
}
private void addRemoveInternetScsiTargetsToAllHosts(final boolean add, final List<HostInternetScsiHbaStaticTarget> lstTargets,
final List<Pair<ManagedObjectReference, String>> lstHosts) throws Exception {
VmwareContext context = getServiceContext();

View File

@ -360,4 +360,8 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
public void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception {
throw new OperationNotSupportedException();
}
public void removeManagedTargetsFromCluster(List<String> managedIqns) throws Exception {
throw new OperationNotSupportedException();
}
}

View File

@ -23,6 +23,7 @@ import java.io.OutputStreamWriter;
import java.net.URI;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@ -79,6 +80,7 @@ import com.cloud.vm.VirtualMachine.State;
import com.google.gson.Gson;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.VirtualDisk;
import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo;
public class VmwareStorageProcessor implements StorageProcessor {
private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
@ -1194,7 +1196,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
Map<String, String> details = disk.getDetails();
morDs = hostService.getVmfsDatastore(hyperHost, VmwareResource.getDatastoreName(iScsiName), storageHost, storagePort,
VmwareResource.trimIqn(iScsiName), details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),
VmwareResource.trimIqn(iScsiName), details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),
details.get(DiskTO.CHAP_TARGET_USERNAME), details.get(DiskTO.CHAP_TARGET_SECRET));
DatastoreMO dsMo = new DatastoreMO(hostService.getServiceContext(null), morDs);
@ -1202,7 +1204,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName());
if (!dsMo.fileExists(volumeDatastorePath)) {
hostService.createVmdk(cmd, dsMo, VmwareResource.getDatastoreName(iScsiName), volumeTO.getSize());
hostService.createVmdk(cmd, dsMo, volumeDatastorePath, volumeTO.getSize());
}
}
else {
@ -1498,6 +1500,14 @@ public class VmwareStorageProcessor implements StorageProcessor {
vmMo.safePowerOff(_shutdown_waitMs);
}
// call this before calling detachAllDisksExcept
// when expunging a VM, we need to see if any of its disks are serviced by managed storage
// if there is one or more disk serviced by managed storage, remove the iSCSI connection(s)
// don't remove the iSCSI connection(s) until the supported disk(s) is/are removed from the VM
// (removeManagedTargetsFromCluster should be called after detachAllDisksExcept and vm.destroy)
List<VirtualDisk> virtualDisks = vmMo.getVirtualDisks();
List<String> managedIqns = getManagedIqnsFromVirtualDisks(virtualDisks);
List<String> detachedDisks = vmMo.detachAllDisksExcept(vol.getPath(), diskInfo != null ? diskInfo.getDiskDeviceBusName() : null);
VmwareStorageLayoutHelper.moveVolumeToRootFolder(new DatacenterMO(context, morDc), detachedDisks);
@ -1505,6 +1515,9 @@ public class VmwareStorageProcessor implements StorageProcessor {
// vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
vmMo.destroy();
// this.hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort);
this.hostService.removeManagedTargetsFromCluster(managedIqns);
for (NetworkDetails netDetails : networks) {
if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) {
if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) {
@ -1555,6 +1568,40 @@ public class VmwareStorageProcessor implements StorageProcessor {
}
}
private List<String> getManagedIqnsFromVirtualDisks(List<VirtualDisk> virtualDisks) {
List<String> managedIqns = new ArrayList<String>();
if (virtualDisks != null) {
for (VirtualDisk virtualDisk : virtualDisks) {
if (virtualDisk.getBacking() instanceof VirtualDiskFlatVer2BackingInfo) {
VirtualDiskFlatVer2BackingInfo backingInfo = (VirtualDiskFlatVer2BackingInfo)virtualDisk.getBacking();
String path = backingInfo.getFileName();
path = new DatastoreFile(path).getFileBaseName();
String search = "-";
int index = path.indexOf(search);
if (index > -1) {
path = path.substring(index + search.length());
index = path.lastIndexOf(search);
if (index > -1) {
path = path.substring(0, index);
if (path.startsWith("iqn.")) {
managedIqns.add(path);
}
}
}
}
}
}
return managedIqns;
}
private Long restoreVolumeFromSecStorage(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
String secStorageUrl, String secStorageDir, String backupName) throws Exception {

View File

@ -317,10 +317,12 @@ public class SolidFirePrimaryDataStoreLifeCycle implements PrimaryDataStoreLifeC
dataStoreHelper.attachZone(dataStore);
List<HostVO> xenServerHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType.XenServer, scope.getScopeId());
List<HostVO> vmWareServerHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType.VMware, scope.getScopeId());
List<HostVO> kvmHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType.KVM, scope.getScopeId());
List<HostVO> hosts = new ArrayList<HostVO>();
hosts.addAll(xenServerHosts);
hosts.addAll(vmWareServerHosts);
hosts.addAll(kvmHosts);
for (HostVO host : hosts) {

View File

@ -1233,6 +1233,19 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
String errorMsg = "Failed to detach volume: " + volume.getName() + " from VM: " + vm.getHostName();
boolean sendCommand = (vm.getState() == State.Running);
Long hostId = vm.getHostId();
if (hostId == null) {
hostId = vm.getLastHostId();
HostVO host = _hostDao.findById(hostId);
if (host != null && host.getHypervisorType() == HypervisorType.VMware) {
sendCommand = true;
}
}
Answer answer = null;
if (sendCommand) {
@ -1251,7 +1264,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
cmd.set_iScsiName(volume.get_iScsiName());
try {
answer = _agentMgr.send(vm.getHostId(), cmd);
answer = _agentMgr.send(hostId, cmd);
} catch (Exception e) {
throw new CloudRuntimeException(errorMsg + " due to: " + e.getMessage());
}

View File

@ -1985,7 +1985,21 @@ public class VirtualMachineMO extends BaseMO {
}
throw new Exception("Unable to find device controller");
}
public List<VirtualDisk> getVirtualDisks() throws Exception {
List<VirtualDisk> virtualDisks = new ArrayList<VirtualDisk>();
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
for (VirtualDevice device : devices) {
if (device instanceof VirtualDisk) {
virtualDisks.add((VirtualDisk)device);
}
}
return virtualDisks;
}
public List<String> detachAllDisksExcept(String vmdkBaseName, String deviceBusName) throws Exception {
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");