Skip to content

Commit 449b5da

Browse files
author
Mike Tutkowski
committed
VMware changes related to managed storage
1 parent a3cec38 commit 449b5da

7 files changed

Lines changed: 147 additions & 13 deletions

File tree

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
// under the License.
1717
package com.cloud.hypervisor.vmware.manager;
1818

19+
import java.util.List;
20+
1921
import com.cloud.agent.api.Command;
2022
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
2123
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
@@ -33,4 +35,5 @@ ManagedObjectReference getVmfsDatastore(VmwareHypervisorHost hyperHost, String d
3335
String iqn, String initiatorChapName, String initiatorChapSecret, String mutualChapName, String mutualChapSecret) throws Exception;
3436
void createVmdk(Command cmd, DatastoreMO dsMo, String volumeDatastorePath, Long volumeSize) throws Exception;
3537
void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception;
38+
void removeManagedTargetsFromCluster(List<String> managedIqns) throws Exception;
3639
}

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2985,7 +2985,9 @@ private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, Virtual
29852985

29862986
VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
29872987
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
2988-
2988+
Map<String, String> details = vol.getDetails();
2989+
boolean isManaged = details != null && Boolean.parseBoolean(details.get(DiskTO.MANAGED));
2990+
29892991
Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid());
29902992
if(volumeDsDetails == null)
29912993
throw new Exception("Primary datastore " + primaryStore.getUuid() + " is not mounted on host.");
@@ -2997,17 +2999,25 @@ private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, Virtual
29972999
String disks[] = diskInfo.getDiskChain();
29983000
for(int i = 0; i < disks.length; i++) {
29993001
DatastoreFile file = new DatastoreFile(disks[i]);
3000-
if(file.getDir() != null && file.getDir().isEmpty()) {
3002+
if (!isManaged && file.getDir() != null && file.getDir().isEmpty()) {
30013003
s_logger.info("Perform run-time datastore folder upgrade. sync " + disks[i] + " to VM folder");
30023004
disks[i] = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(
30033005
dcMo, vmMo.getName(), dsMo, file.getFileBaseName());
30043006
}
30053007
}
30063008
return disks;
3007-
}
3008-
3009-
String datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(
3010-
dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
3009+
}
3010+
3011+
final String datastoreDiskPath;
3012+
3013+
if (isManaged) {
3014+
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
3015+
}
3016+
else {
3017+
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(
3018+
dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
3019+
}
3020+
30113021
if(!dsMo.fileExists(datastoreDiskPath)) {
30123022
s_logger.warn("Volume " + volumeTO.getId() + " does not seem to exist on datastore, out of sync? path: " + datastoreDiskPath);
30133023
}
@@ -3223,7 +3233,10 @@ private VirtualMachineDiskInfo getMatchingExistingDisk(VirtualMachineDiskInfoBui
32233233
if(diskInfoBuilder != null) {
32243234
VolumeObjectTO volume = (VolumeObjectTO)vol.getData();
32253235

3226-
VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(volume.getPath());
3236+
Map<String, String> details = vol.getDetails();
3237+
boolean isManaged = details != null && Boolean.parseBoolean(details.get(DiskTO.MANAGED));
3238+
3239+
VirtualMachineDiskInfo diskInfo = diskInfoBuilder.getDiskInfoByBackingFileBaseName(isManaged ? new DatastoreFile(volume.getPath()).getFileBaseName() : volume.getPath());
32273240
if(diskInfo != null) {
32283241
s_logger.info("Found existing disk info from volume path: " + volume.getPath());
32293242
return diskInfo;
@@ -3421,7 +3434,16 @@ private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastor
34213434
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
34223435
String poolUuid = primaryStore.getUuid();
34233436
if(poolMors.get(poolUuid) == null) {
3424-
ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid);
3437+
boolean isManaged = false;
3438+
String iScsiName = null;
3439+
Map<String, String> details = vol.getDetails();
3440+
3441+
if (details != null) {
3442+
isManaged = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
3443+
iScsiName = details.get(DiskTO.IQN);
3444+
}
3445+
3446+
ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(iScsiName) : poolUuid);
34253447
if (morDataStore == null) {
34263448
String msg = "Failed to get the mounted datastore for the volume's pool " + poolUuid;
34273449
s_logger.error(msg);
@@ -4534,7 +4556,7 @@ protected Answer execute(AttachVolumeCommand cmd) {
45344556
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName());
45354557

45364558
if (!dsMo.fileExists(volumeDatastorePath)) {
4537-
createVmdk(cmd, dsMo, VmwareResource.getDatastoreName(cmd.get_iScsiName()), cmd.getVolumeSize());
4559+
createVmdk(cmd, dsMo, volumeDatastorePath, cmd.getVolumeSize());
45384560
}
45394561
}
45404562
else {
@@ -4592,6 +4614,35 @@ protected Answer execute(AttachVolumeCommand cmd) {
45924614
}
45934615
}
45944616

4617+
@Override
4618+
public void removeManagedTargetsFromCluster(List<String> iqns) throws Exception {
4619+
List<HostInternetScsiHbaStaticTarget> lstManagedTargets = new ArrayList<HostInternetScsiHbaStaticTarget>();
4620+
4621+
VmwareContext context = getServiceContext();
4622+
VmwareHypervisorHost hyperHost = getHyperHost(context);
4623+
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
4624+
ClusterMO cluster = new ClusterMO(context, morCluster);
4625+
List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts();
4626+
HostMO host = new HostMO(context, lstHosts.get(0).first());
4627+
HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
4628+
4629+
for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) {
4630+
if (hba instanceof HostInternetScsiHba) {
4631+
List<HostInternetScsiHbaStaticTarget> lstTargets = ((HostInternetScsiHba)hba).getConfiguredStaticTarget();
4632+
4633+
if (lstTargets != null) {
4634+
for (HostInternetScsiHbaStaticTarget target : lstTargets) {
4635+
if (iqns.contains(target.getIScsiName())) {
4636+
lstManagedTargets.add(target);
4637+
}
4638+
}
4639+
}
4640+
}
4641+
}
4642+
4643+
addRemoveInternetScsiTargetsToAllHosts(false, lstManagedTargets, lstHosts);
4644+
}
4645+
45954646
private void addRemoveInternetScsiTargetsToAllHosts(final boolean add, final List<HostInternetScsiHbaStaticTarget> lstTargets,
45964647
final List<Pair<ManagedObjectReference, String>> lstHosts) throws Exception {
45974648
VmwareContext context = getServiceContext();

plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,4 +360,8 @@ public void createVmdk(Command cmd, DatastoreMO dsMo, String volumeDatastorePath
360360
public void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception {
361361
throw new OperationNotSupportedException();
362362
}
363+
364+
public void removeManagedTargetsFromCluster(List<String> managedIqns) throws Exception {
365+
throw new OperationNotSupportedException();
366+
}
363367
}

plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.net.URI;
2424
import java.rmi.RemoteException;
2525
import java.util.HashMap;
26+
import java.util.ArrayList;
2627
import java.util.List;
2728
import java.util.Map;
2829
import java.util.UUID;
@@ -79,6 +80,7 @@
7980
import com.google.gson.Gson;
8081
import com.vmware.vim25.ManagedObjectReference;
8182
import com.vmware.vim25.VirtualDisk;
83+
import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo;
8284

8385
public class VmwareStorageProcessor implements StorageProcessor {
8486
private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
@@ -1194,15 +1196,15 @@ private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean
11941196
Map<String, String> details = disk.getDetails();
11951197

11961198
morDs = hostService.getVmfsDatastore(hyperHost, VmwareResource.getDatastoreName(iScsiName), storageHost, storagePort,
1197-
VmwareResource.trimIqn(iScsiName), details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),
1199+
VmwareResource.trimIqn(iScsiName), details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),
11981200
details.get(DiskTO.CHAP_TARGET_USERNAME), details.get(DiskTO.CHAP_TARGET_SECRET));
11991201

12001202
DatastoreMO dsMo = new DatastoreMO(hostService.getServiceContext(null), morDs);
12011203

12021204
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName());
12031205

12041206
if (!dsMo.fileExists(volumeDatastorePath)) {
1205-
hostService.createVmdk(cmd, dsMo, VmwareResource.getDatastoreName(iScsiName), volumeTO.getSize());
1207+
hostService.createVmdk(cmd, dsMo, volumeDatastorePath, volumeTO.getSize());
12061208
}
12071209
}
12081210
else {
@@ -1498,13 +1500,24 @@ public Answer deleteVolume(DeleteCommand cmd) {
14981500
vmMo.safePowerOff(_shutdown_waitMs);
14991501
}
15001502

1503+
// call this before calling detachAllDisksExcept
1504+
// when expunging a VM, we need to see if any of its disks are serviced by managed storage
1505+
// if there is one or more disk serviced by managed storage, remove the iSCSI connection(s)
1506+
// don't remove the iSCSI connection(s) until the supported disk(s) is/are removed from the VM
1507+
// (removeManagedTargetsFromCluster should be called after detachAllDisksExcept and vm.destroy)
1508+
List<VirtualDisk> virtualDisks = vmMo.getVirtualDisks();
1509+
List<String> managedIqns = getManagedIqnsFromVirtualDisks(virtualDisks);
1510+
15011511
List<String> detachedDisks = vmMo.detachAllDisksExcept(vol.getPath(), diskInfo != null ? diskInfo.getDiskDeviceBusName() : null);
15021512
VmwareStorageLayoutHelper.moveVolumeToRootFolder(new DatacenterMO(context, morDc), detachedDisks);
15031513

15041514
// let vmMo.destroy to delete volume for us
15051515
// vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
15061516
vmMo.destroy();
15071517

1518+
// this.hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort);
1519+
this.hostService.removeManagedTargetsFromCluster(managedIqns);
1520+
15081521
for (NetworkDetails netDetails : networks) {
15091522
if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) {
15101523
if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) {
@@ -1555,6 +1568,40 @@ public Answer deleteVolume(DeleteCommand cmd) {
15551568
}
15561569
}
15571570

1571+
private List<String> getManagedIqnsFromVirtualDisks(List<VirtualDisk> virtualDisks) {
1572+
List<String> managedIqns = new ArrayList<String>();
1573+
1574+
if (virtualDisks != null) {
1575+
for (VirtualDisk virtualDisk : virtualDisks) {
1576+
if (virtualDisk.getBacking() instanceof VirtualDiskFlatVer2BackingInfo) {
1577+
VirtualDiskFlatVer2BackingInfo backingInfo = (VirtualDiskFlatVer2BackingInfo)virtualDisk.getBacking();
1578+
String path = backingInfo.getFileName();
1579+
1580+
path = new DatastoreFile(path).getFileBaseName();
1581+
1582+
String search = "-";
1583+
int index = path.indexOf(search);
1584+
1585+
if (index > -1) {
1586+
path = path.substring(index + search.length());
1587+
1588+
index = path.lastIndexOf(search);
1589+
1590+
if (index > -1) {
1591+
path = path.substring(0, index);
1592+
1593+
if (path.startsWith("iqn.")) {
1594+
managedIqns.add(path);
1595+
}
1596+
}
1597+
}
1598+
}
1599+
}
1600+
}
1601+
1602+
return managedIqns;
1603+
}
1604+
15581605
private Long restoreVolumeFromSecStorage(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
15591606
String secStorageUrl, String secStorageDir, String backupName) throws Exception {
15601607

plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/lifecycle/SolidFirePrimaryDataStoreLifeCycle.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,12 @@ public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType h
317317
dataStoreHelper.attachZone(dataStore);
318318

319319
List<HostVO> xenServerHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType.XenServer, scope.getScopeId());
320+
List<HostVO> vmWareServerHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType.VMware, scope.getScopeId());
320321
List<HostVO> kvmHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType.KVM, scope.getScopeId());
321322
List<HostVO> hosts = new ArrayList<HostVO>();
322323

323324
hosts.addAll(xenServerHosts);
325+
hosts.addAll(vmWareServerHosts);
324326
hosts.addAll(kvmHosts);
325327

326328
for (HostVO host : hosts) {

server/src/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,19 @@ public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) {
12331233

12341234
String errorMsg = "Failed to detach volume: " + volume.getName() + " from VM: " + vm.getHostName();
12351235
boolean sendCommand = (vm.getState() == State.Running);
1236+
1237+
Long hostId = vm.getHostId();
1238+
1239+
if (hostId == null) {
1240+
hostId = vm.getLastHostId();
1241+
1242+
HostVO host = _hostDao.findById(hostId);
1243+
1244+
if (host != null && host.getHypervisorType() == HypervisorType.VMware) {
1245+
sendCommand = true;
1246+
}
1247+
}
1248+
12361249
Answer answer = null;
12371250

12381251
if (sendCommand) {
@@ -1251,7 +1264,7 @@ public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) {
12511264
cmd.set_iScsiName(volume.get_iScsiName());
12521265

12531266
try {
1254-
answer = _agentMgr.send(vm.getHostId(), cmd);
1267+
answer = _agentMgr.send(hostId, cmd);
12551268
} catch (Exception e) {
12561269
throw new CloudRuntimeException(errorMsg + " due to: " + e.getMessage());
12571270
}

vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,21 @@ private String getDeviceBusName(List<VirtualDevice> allDevices, VirtualDevice th
19851985
}
19861986
throw new Exception("Unable to find device controller");
19871987
}
1988-
1988+
1989+
public List<VirtualDisk> getVirtualDisks() throws Exception {
1990+
List<VirtualDisk> virtualDisks = new ArrayList<VirtualDisk>();
1991+
1992+
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
1993+
1994+
for (VirtualDevice device : devices) {
1995+
if (device instanceof VirtualDisk) {
1996+
virtualDisks.add((VirtualDisk)device);
1997+
}
1998+
}
1999+
2000+
return virtualDisks;
2001+
}
2002+
19892003
public List<String> detachAllDisksExcept(String vmdkBaseName, String deviceBusName) throws Exception {
19902004
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
19912005

0 commit comments

Comments
 (0)