diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java index 4906b2fdd21..2b44071a87c 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java @@ -19,11 +19,16 @@ package com.cloud.hypervisor.vmware.manager; import com.cloud.agent.api.Command; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost; import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.vmware.vim25.ManagedObjectReference; public interface VmwareHostService { - VmwareContext getServiceContext(Command cmd); - void invalidateServiceContext(VmwareContext context); - VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd); + VmwareContext getServiceContext(Command cmd); + void invalidateServiceContext(VmwareContext context); + VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd); - String getWorkerName(VmwareContext context, Command cmd, int workerSequence); + String getWorkerName(VmwareContext context, Command cmd, int workerSequence); + + ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort, + String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception; + void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception; } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 35735006aab..b107df9562b 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -4063,45 +4063,44 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - protected ManagedObjectReference handleDatastoreAndVmdk(AttachVolumeCommand cmd) throws Exception { - ManagedObjectReference morDs = null; - + public ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort, + String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception { VmwareContext context = getServiceContext(); VmwareHypervisorHost hyperHost = getHyperHost(context); - String iqn = cmd.get_iScsiName(); + ManagedObjectReference morDs = createVmfsDatastore(hyperHost, iqn, + storageHost, storagePort, iqn, + initiatorUsername, initiatorPassword, + targetUsername, targetPassword); - if (cmd.getAttach()) { - morDs = createVmfsDatastore(hyperHost, iqn, - cmd.getStorageHost(), cmd.getStoragePort(), iqn, - cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), - cmd.getChapTargetUsername(), cmd.getChapTargetPassword()); + DatastoreMO dsMo = new DatastoreMO(context, morDs); - DatastoreMO dsMo = new DatastoreMO(context, morDs); + String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName()); - String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName()); + if (!dsMo.fileExists(volumeDatastorePath)) { + String dummyVmName = getWorkerName(context, cmd, 0); - if (!dsMo.fileExists(volumeDatastorePath)) { - String dummyVmName = getWorkerName(context, cmd, 0); + VirtualMachineMO vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName); - VirtualMachineMO vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName); - - if (vmMo == null) { - throw new Exception("Unable to create a dummy VM for volume creation"); - } - - vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dsMo.getSummary().getFreeSpace()), - morDs, vmMo.getScsiDeviceControllerKey()); - vmMo.detachDisk(volumeDatastorePath, false); + if (vmMo == null) { + throw new Exception("Unable to create a dummy VM for volume creation"); } - } - else { - deleteVmfsDatastore(hyperHost, iqn, cmd.getStorageHost(), cmd.getStoragePort(), iqn); + + vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dsMo.getSummary().getFreeSpace()), + morDs, vmMo.getScsiDeviceControllerKey()); + vmMo.detachDisk(volumeDatastorePath, false); } return morDs; } + public void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception { + VmwareContext context = getServiceContext(); + VmwareHypervisorHost hyperHost = getHyperHost(context); + + deleteVmfsDatastore(hyperHost, iqn, storageHost, storagePort, iqn); + } + protected Answer execute(AttachVolumeCommand cmd) { if (s_logger.isInfoEnabled()) { s_logger.info("Executing resource AttachVolumeCommand: " + _gson.toJson(cmd)); @@ -4124,7 +4123,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ManagedObjectReference morDs = null; if (cmd.getAttach() && cmd.isManaged()) { - morDs = handleDatastoreAndVmdk(cmd); + morDs = handleDatastoreAndVmdkAttach(cmd, cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort(), + cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), + cmd.getChapTargetUsername(), cmd.getChapTargetPassword()); } else { morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getPoolUuid()); @@ -4142,6 +4143,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (datastoreVolumePath == null) { throw new CloudRuntimeException("Unable to find file " + cmd.getVolumePath() + ".vmdk in datastore " + dsMo.getName()); } + AttachVolumeAnswer answer = new AttachVolumeAnswer(cmd, cmd.getDeviceId(), datastoreVolumePath); if (cmd.getAttach()) { vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs); @@ -4150,7 +4152,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vmMo.detachDisk(datastoreVolumePath, false); if (cmd.isManaged()) { - handleDatastoreAndVmdk(cmd); + handleDatastoreAndVmdkDetach(cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort()); } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java index 22ba59f36ca..dddc80550ae 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java @@ -18,6 +18,8 @@ package com.cloud.storage.resource; import java.util.List; +import javax.naming.OperationNotSupportedException; + import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.resource.SecondaryStorageResourceHandler; import org.apache.log4j.Logger; @@ -341,4 +343,13 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe assert (false); return true; } + + public ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort, + String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception { + throw new OperationNotSupportedException(); + } + + public void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception { + throw new OperationNotSupportedException(); + } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java index 421fb223cd9..411380305d1 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -42,6 +42,7 @@ import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AttachVolumeCommand; import com.cloud.agent.api.BackupSnapshotAnswer; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer; @@ -767,12 +768,20 @@ public class VmwareStorageProcessor implements StorageProcessor { return this.attachIso(cmd.getDisk(), true, cmd.getVmName()); } - @Override - public Answer attachVolume(AttachCommand cmd) { - return this.attachVolume(cmd, cmd.getDisk(), true, cmd.getVmName()); - } - - private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, String vmName) { + @Override + public Answer attachVolume(AttachCommand cmd) { + return this.attachVolume(cmd, cmd.getDisk(), true, cmd.isManaged(), cmd.getVmName(), cmd.get_iScsiName(), + cmd.getStorageHost(), cmd.getStoragePort(), cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), + cmd.getChapTargetUsername(), cmd.getChapTargetPassword()); + } + + private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean isManaged, String vmName) { + return attachVolume(cmd, disk, isAttach, isManaged, vmName, null, null, 0, null, null, null, null); + } + + private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean isManaged, String vmName, + String iScsiName, String storageHost, int storagePort, String initiatorUsername, String initiatorPassword, + String targetUsername, String targetPassword) { VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData(); PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); @@ -785,22 +794,37 @@ public class VmwareStorageProcessor implements StorageProcessor { throw new Exception(msg); } - ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid()); - if (morDs == null) { - String msg = "Unable to find the mounted datastore to execute AttachVolumeCommand, vmName: " + vmName; - s_logger.error(msg); - throw new Exception(msg); - } + ManagedObjectReference morDs = null; + + if (isAttach && isManaged) { + morDs = this.hostService.handleDatastoreAndVmdkAttach(cmd, iScsiName, storageHost, storagePort, + initiatorUsername, initiatorPassword, targetUsername, targetPassword); + } + else { + morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid()); + } + + if (morDs == null) { + String msg = "Unable to find the mounted datastore to execute AttachVolumeCommand, vmName: " + vmName; + s_logger.error(msg); + throw new Exception(msg); + } DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs); String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeTO.getPath()); + disk.setVdiUuid(datastoreVolumePath); + AttachAnswer answer = new AttachAnswer(disk); if (isAttach) { vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs); } else { vmMo.removeAllSnapshots(); vmMo.detachDisk(datastoreVolumePath, false); + + if (isManaged) { + this.hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort); + } } return answer; @@ -916,7 +940,7 @@ public class VmwareStorageProcessor implements StorageProcessor { @Override public Answer dettachVolume(DettachCommand cmd) { - return this.attachVolume(cmd, cmd.getDisk(), false, cmd.getVmName()); + return this.attachVolume(cmd, cmd.getDisk(), false, cmd.isManaged(), cmd.getVmName()); } protected VirtualMachineMO prepareVolumeHostDummyVm(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception { diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index 16185744a33..65838edf324 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -1648,10 +1648,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { volumeToAttach = _volsDao.findById(volumeToAttach.getId()); if (volumeToAttachStoragePool.isManaged() && - volumeToAttach.getPath() == null) { - volumeToAttach.setPath(answer.getDisk().getVdiUuid()); + volumeToAttach.getPath() == null) { + volumeToAttach.setPath(answer.getDisk().getVdiUuid()); - _volsDao.update(volumeToAttach.getId(), volumeToAttach); + _volsDao.update(volumeToAttach.getId(), volumeToAttach); } } else { _volsDao.attachVolume(volumeToAttach.getId(), vm.getId(), deviceId);