You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mt...@apache.org on 2014/04/19 18:32:03 UTC
git commit: updated refs/heads/4.4-forward to d40c465
Repository: cloudstack
Updated Branches:
refs/heads/4.4-forward 8d371ab03 -> d40c465a3
CLOUDSTACK-6170 (VMware root-disk support for managed storage)
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/d40c465a
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/d40c465a
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/d40c465a
Branch: refs/heads/4.4-forward
Commit: d40c465a32b9b447d363e70ec718ec48e290da8a
Parents: 8d371ab
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Thu Apr 17 12:55:19 2014 -0600
Committer: Mike Tutkowski <mi...@solidfire.com>
Committed: Sat Apr 19 10:30:46 2014 -0600
----------------------------------------------------------------------
.../storage/resource/StoragePoolResource.java | 4 -
.../vmware/manager/VmwareHostService.java | 16 -
.../vmware/resource/VmwareResource.java | 727 +------------------
.../VmwareSecondaryStorageResourceHandler.java | 26 -
.../resource/VmwareStorageProcessor.java | 410 ++++++++++-
5 files changed, 406 insertions(+), 777 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d40c465a/core/src/com/cloud/storage/resource/StoragePoolResource.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/StoragePoolResource.java b/core/src/com/cloud/storage/resource/StoragePoolResource.java
index 5ec8f0e..a87dfec 100644
--- a/core/src/com/cloud/storage/resource/StoragePoolResource.java
+++ b/core/src/com/cloud/storage/resource/StoragePoolResource.java
@@ -19,8 +19,6 @@ package com.cloud.storage.resource;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
-import com.cloud.agent.api.storage.CreateAnswer;
-import com.cloud.agent.api.storage.CreateCommand;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
@@ -33,6 +31,4 @@ public interface StoragePoolResource {
Answer execute(DestroyCommand cmd);
CopyVolumeAnswer execute(CopyVolumeCommand cmd);
-
- CreateAnswer execute(CreateCommand cmd);
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d40c465a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java
----------------------------------------------------------------------
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 c232a60..14630b3 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
@@ -16,10 +16,6 @@
// under the License.
package com.cloud.hypervisor.vmware.manager;
-import java.util.List;
-
-import com.vmware.vim25.ManagedObjectReference;
-
import com.cloud.agent.api.Command;
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
import com.cloud.hypervisor.vmware.util.VmwareContext;
@@ -32,16 +28,4 @@ public interface VmwareHostService {
VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd);
String getWorkerName(VmwareContext context, Command cmd, int workerSequence);
-
- ManagedObjectReference prepareManagedDatastore(VmwareHypervisorHost hyperHost, String iScsiName,
- String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
- String chapTargetUsername, String chapTargetSecret) throws Exception;
-
- ManagedObjectReference prepareManagedStorage(VmwareHypervisorHost hyperHost, String iScsiName,
- String storageHost, int storagePort, String volumeName, String chapInitiatorUsername, String chapInitiatorSecret,
- String chapTargetUsername, String chapTargetSecret, long size, Command cmd) throws Exception;
-
- void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception;
-
- void removeManagedTargetsFromCluster(List<String> managedIqns) throws Exception;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d40c465a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
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 e89777d..945773e 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
@@ -38,9 +38,6 @@ import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
@@ -62,14 +59,6 @@ import com.vmware.vim25.DynamicProperty;
import com.vmware.vim25.HostCapability;
import com.vmware.vim25.HostHostBusAdapter;
import com.vmware.vim25.HostInternetScsiHba;
-import com.vmware.vim25.HostInternetScsiHbaAuthenticationProperties;
-import com.vmware.vim25.HostInternetScsiHbaStaticTarget;
-import com.vmware.vim25.HostInternetScsiTargetTransport;
-import com.vmware.vim25.HostScsiDisk;
-import com.vmware.vim25.HostScsiTopology;
-import com.vmware.vim25.HostScsiTopologyInterface;
-import com.vmware.vim25.HostScsiTopologyLun;
-import com.vmware.vim25.HostScsiTopologyTarget;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.OptionValue;
@@ -109,8 +98,6 @@ import org.apache.cloudstack.storage.to.VolumeObjectTO;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.AttachIsoCommand;
-import com.cloud.agent.api.AttachVolumeAnswer;
-import com.cloud.agent.api.AttachVolumeCommand;
import com.cloud.agent.api.BackupSnapshotAnswer;
import com.cloud.agent.api.BackupSnapshotCommand;
import com.cloud.agent.api.CheckHealthAnswer;
@@ -202,8 +189,6 @@ import com.cloud.agent.api.routing.SetNetworkACLCommand;
import com.cloud.agent.api.routing.SetSourceNatCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
-import com.cloud.agent.api.storage.CreateAnswer;
-import com.cloud.agent.api.storage.CreateCommand;
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.MigrateVolumeAnswer;
@@ -240,7 +225,6 @@ import com.cloud.hypervisor.vmware.mo.DatastoreFile;
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
import com.cloud.hypervisor.vmware.mo.DiskControllerType;
import com.cloud.hypervisor.vmware.mo.FeatureKeyConstants;
-import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.hypervisor.vmware.mo.HostStorageSystemMO;
import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
@@ -276,7 +260,6 @@ import com.cloud.utils.DateUtil;
import com.cloud.utils.ExecutionResult;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
-import com.cloud.utils.StringUtils;
import com.cloud.utils.Ternary;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
@@ -285,7 +268,6 @@ import com.cloud.utils.mgmt.JmxUtil;
import com.cloud.utils.mgmt.PropertyMapDynamicBean;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.ssh.SshHelper;
-import com.cloud.vm.DiskProfile;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.PowerState;
import com.cloud.vm.VirtualMachine.State;
@@ -340,6 +322,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
protected volatile long _cmdSequence = 1;
protected StorageSubsystemCommandHandler storageHandler;
+ private VmwareStorageProcessor _storageProcessor;
protected VirtualRoutingResource _vrResource;
@@ -390,9 +373,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
mbean.addProp("Name", cmd.getClass().getSimpleName());
Class<? extends Command> clz = cmd.getClass();
- if (clz == CreateCommand.class) {
- answer = execute((CreateCommand)cmd);
- } else if (cmd instanceof NetworkElementCommand) {
+ if (cmd instanceof NetworkElementCommand) {
return _vrResource.executeRequest((NetworkElementCommand)cmd);
} else if (clz == ReadyCommand.class) {
answer = execute((ReadyCommand)cmd);
@@ -430,8 +411,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
answer = execute((DeleteStoragePoolCommand)cmd);
} else if (clz == CopyVolumeCommand.class) {
answer = execute((CopyVolumeCommand)cmd);
- } else if (clz == AttachVolumeCommand.class) {
- answer = execute((AttachVolumeCommand)cmd);
} else if (clz == AttachIsoCommand.class) {
answer = execute((AttachIsoCommand)cmd);
} else if (clz == ValidateSnapshotCommand.class) {
@@ -1160,88 +1139,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return new ExecutionResult(true, null);
}
- private ExecutionResult NetworkElementCommandnup(IpAssocCommand cmd) {
- VmwareContext context = getServiceContext();
- try {
- VmwareHypervisorHost hyperHost = getHyperHost(context);
-
- IpAddressTO[] ips = cmd.getIpAddresses();
- String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
- VmwareResource.getRouterSshControlIp(cmd);
-
- VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(routerName);
-
- // command may sometimes be redirect to a wrong host, we relax
- // the check and will try to find it within cluster
- if (vmMo == null) {
- if (hyperHost instanceof HostMO) {
- ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor());
- vmMo = clusterMo.findVmOnHyperHost(routerName);
- }
- }
-
- if (vmMo == null) {
- String msg = "Router " + routerName + " no longer exists to execute IPAssoc command";
- s_logger.error(msg);
- throw new Exception(msg);
- }
-
- for (IpAddressTO ip : ips) {
- /**
- * TODO support other networks
- */
- URI broadcastUri = BroadcastDomainType.fromString(ip.getBroadcastUri());
- if (BroadcastDomainType.getSchemeValue(broadcastUri) != BroadcastDomainType.Vlan) {
- throw new InternalErrorException("Unable to assign a public IP to a VIF on network " + ip.getBroadcastUri());
- }
- String vlanId = BroadcastDomainType.getValue(broadcastUri);
-
- String publicNeworkName = HypervisorHostHelper.getPublicNetworkNamePrefix(vlanId);
- Pair<Integer, VirtualDevice> publicNicInfo = vmMo.getNicDeviceIndex(publicNeworkName);
-
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Find public NIC index, public network name: " + publicNeworkName + ", index: " + publicNicInfo.first());
- }
-
- boolean removeVif = false;
- if (!ip.isAdd() && ip.isFirstIP()) {
- removeVif = true;
-
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Unplug NIC " + publicNicInfo.first());
- }
- }
-
- if (publicNicInfo.first().intValue() < 0) {
- String msg = "Failed to find DomR VIF to associate/disassociate IP with.";
- s_logger.error(msg);
- throw new InternalErrorException(msg);
- }
-
- if (removeVif) {
- String nicMasksStr = vmMo.getCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK);
- int nicMasks = Integer.parseInt(nicMasksStr);
- nicMasks &= ~(1 << publicNicInfo.first().intValue());
- vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMasks));
-
- HostMO hostMo = vmMo.getRunningHost();
- List<NetworkDetails> networks = vmMo.getNetworksWithDetails();
- for (NetworkDetails netDetails : networks) {
- if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) {
- if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) {
- cleanupNetwork(hostMo, netDetails);
- }
- }
- }
- }
- }
- } catch (Throwable e) {
- s_logger.error("Unexpected exception: " + e.toString() + " will shortcut rest of IPAssoc commands", e);
- return new ExecutionResult(false, e.toString());
- }
- return new ExecutionResult(true, null);
- }
-
@Override
public ExecutionResult executeInVR(String routerIP, String script, String args) {
return executeInVR(routerIP, script, args, 120);
@@ -1824,32 +1721,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
vmMo.ensureScsiDeviceController();
}
- @Override
- public ManagedObjectReference prepareManagedDatastore(VmwareHypervisorHost hyperHost, String iScsiName,
- String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
- String chapTargetUsername, String chapTargetSecret) throws Exception {
- return getVmfsDatastore(hyperHost, VmwareResource.getDatastoreName(iScsiName), storageHost, storagePort,
- VmwareResource.trimIqn(iScsiName), chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
- }
-
- @Override
- public ManagedObjectReference prepareManagedStorage(VmwareHypervisorHost hyperHost, String iScsiName,
- String storageHost, int storagePort, String volumeName, String chapInitiatorUsername, String chapInitiatorSecret,
- String chapTargetUsername, String chapTargetSecret, long size, Command cmd) throws Exception {
- ManagedObjectReference morDs = prepareManagedDatastore(hyperHost, iScsiName, storageHost, storagePort,
- chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
-
- DatastoreMO dsMo = new DatastoreMO(getServiceContext(null), morDs);
-
- String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeName != null ? volumeName : dsMo.getName());
-
- if (!dsMo.fileExists(volumeDatastorePath)) {
- createVmdk(cmd, dsMo, volumeDatastorePath, size);
- }
-
- return morDs;
- }
-
int getReservedMemoryMb(VirtualMachineTO vmSpec) {
if (vmSpec.getDetails().get(Config.VmwareReserveMem.key()).equalsIgnoreCase("true")) {
return (int)(vmSpec.getMinRam() / (1024 * 1024));
@@ -2348,7 +2219,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
// if the datastore is not present, we need to discover the iSCSI device that will support it,
// create the datastore, and create a VMDK file in the datastore
if (morDatastore == null) {
- morDatastore = prepareManagedStorage(hyperHost, iScsiName,
+ morDatastore = _storageProcessor.prepareManagedStorage(context, hyperHost, iScsiName,
details.get(DiskTO.STORAGE_HOST), Integer.parseInt(details.get(DiskTO.STORAGE_PORT)),
volumeTO.getVolumeType() == Volume.Type.ROOT ? volumeTO.getName() : null,
details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),
@@ -3383,404 +3254,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return str.replace('/', '-');
}
- private static String trimIqn(String iqn) {
- String[] tmp = iqn.split("/");
-
- if (tmp.length != 3) {
- String msg = "Wrong format for iScsi path: " + iqn + ". It should be formatted as '/targetIQN/LUN'.";
-
- s_logger.warn(msg);
-
- throw new CloudRuntimeException(msg);
- }
-
- return tmp[1].trim();
- }
-
- private void createVmdk(Command cmd, DatastoreMO dsMo, String vmdkDatastorePath, Long volumeSize) throws Exception {
- VmwareContext context = getServiceContext();
- VmwareHypervisorHost hyperHost = getHyperHost(context);
-
- String dummyVmName = getWorkerName(context, cmd, 0);
-
- VirtualMachineMO vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
-
- if (vmMo == null) {
- throw new Exception("Unable to create a dummy VM for volume creation");
- }
-
- Long volumeSizeToUse = volumeSize < dsMo.getSummary().getFreeSpace() ? volumeSize : dsMo.getSummary().getFreeSpace();
-
- vmMo.createDisk(vmdkDatastorePath, getMBsFromBytes(volumeSizeToUse), dsMo.getMor(), vmMo.getScsiDeviceControllerKey());
- vmMo.detachDisk(vmdkDatastorePath, false);
- vmMo.destroy();
- }
-
- @Override
- public void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception {
- VmwareContext context = getServiceContext();
- VmwareHypervisorHost hyperHost = getHyperHost(context);
-
- deleteVmfsDatastore(hyperHost, VmwareResource.getDatastoreName(iqn), storageHost, storagePort, VmwareResource.trimIqn(iqn));
- }
-
- protected Answer execute(AttachVolumeCommand cmd) {
- if (s_logger.isInfoEnabled()) {
- s_logger.info("Executing resource AttachVolumeCommand: " + _gson.toJson(cmd));
- }
-
- /*
- * AttachVolumeCommand { "attach":true,"vmName":"i-2-1-KY","pooltype":"NetworkFilesystem",
- * "volumeFolder":"/export/home/kelven/vmware-test/primary", "volumePath":"uuid",
- * "volumeName":"volume name","deviceId":1 }
- */
- try {
- VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext());
- VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
- if (vmMo == null) {
- String msg = "Unable to find the VM to execute AttachVolumeCommand, vmName: " + cmd.getVmName();
- s_logger.error(msg);
- throw new Exception(msg);
- }
-
- ManagedObjectReference morDs = null;
-
- if (cmd.getAttach() && cmd.isManaged()) {
- morDs = prepareManagedStorage(hyperHost, cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort(), null,
- cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(),
- cmd.getChapTargetUsername(), cmd.getChapTargetPassword(), cmd.getVolumeSize(), cmd);
- }
- else {
- morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getPoolUuid());
- }
-
- if (morDs == null) {
- String msg = "Unable to find the mounted datastore to execute AttachVolumeCommand, vmName: " + cmd.getVmName();
- s_logger.error(msg);
- throw new Exception(msg);
- }
-
- DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDs);
-
- String datastoreVolumePath = null;
-
- if (cmd.isManaged()) {
- datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
- } else {
- VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), cmd.getVmName(), dsMo, cmd.getVolumePath());
-
- datastoreVolumePath = dsMo.searchFileInSubFolders(cmd.getVolumePath() + ".vmdk", true);
- }
-
- assert (datastoreVolumePath != null) : "Virtual disk file must exist in specified datastore for attach/detach operations.";
- 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);
- } else {
- vmMo.removeAllSnapshots();
- vmMo.detachDisk(datastoreVolumePath, false);
-
- if (cmd.isManaged()) {
- handleDatastoreAndVmdkDetach(cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort());
- } else {
- VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, cmd.getVolumePath());
- }
- }
-
- return answer;
- } catch (Throwable e) {
- if (e instanceof RemoteException) {
- s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
- invalidateServiceContext();
- }
-
- String msg = "AttachVolumeCommand failed due to " + VmwareHelper.getExceptionMessage(e);
- s_logger.error(msg, e);
- return new AttachVolumeAnswer(cmd, msg);
- }
- }
-
- @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);
-
- rescanAllHosts(lstHosts);
- }
-
- private void addRemoveInternetScsiTargetsToAllHosts(final boolean add, final List<HostInternetScsiHbaStaticTarget> lstTargets,
- final List<Pair<ManagedObjectReference, String>> lstHosts) throws Exception {
- VmwareContext context = getServiceContext();
-
- ExecutorService executorService = Executors.newFixedThreadPool(lstHosts.size());
-
- final List<Exception> exceptions = new ArrayList<Exception>();
-
- for (Pair<ManagedObjectReference, String> hostPair : lstHosts) {
- HostMO host = new HostMO(context, hostPair.first());
- HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
-
- boolean iScsiHbaConfigured = false;
-
- for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) {
- if (hba instanceof HostInternetScsiHba) {
- // just finding an instance of HostInternetScsiHba means that we have found at least one configured iSCSI HBA
- // at least one iSCSI HBA must be configured before a CloudStack user can use this host for iSCSI storage
- iScsiHbaConfigured = true;
-
- final String iScsiHbaDevice = hba.getDevice();
-
- final HostStorageSystemMO hss = hostStorageSystem;
-
- executorService.submit(new Thread() {
- @Override
- public void run() {
- try {
- if (add) {
- hss.addInternetScsiStaticTargets(iScsiHbaDevice, lstTargets);
- } else {
- hss.removeInternetScsiStaticTargets(iScsiHbaDevice, lstTargets);
- }
-
- hss.rescanHba(iScsiHbaDevice);
- hss.rescanVmfs();
- } catch (Exception ex) {
- synchronized (exceptions) {
- exceptions.add(ex);
- }
- }
- }
- });
- }
- }
-
- if (!iScsiHbaConfigured) {
- throw new Exception("An iSCSI HBA must be configured before a host can use iSCSI storage.");
- }
- }
-
- executorService.shutdown();
-
- if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES)) {
- throw new Exception("The system timed out before completing the task 'rescanAllHosts'.");
- }
-
- if (exceptions.size() > 0) {
- throw new Exception(exceptions.get(0).getMessage());
- }
- }
-
- private void rescanAllHosts(final List<Pair<ManagedObjectReference, String>> lstHosts) throws Exception {
- VmwareContext context = getServiceContext();
-
- ExecutorService executorService = Executors.newFixedThreadPool(lstHosts.size());
-
- final List<Exception> exceptions = new ArrayList<Exception>();
-
- for (Pair<ManagedObjectReference, String> hostPair : lstHosts) {
- HostMO host = new HostMO(context, hostPair.first());
- HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
-
- boolean iScsiHbaConfigured = false;
-
- for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) {
- if (hba instanceof HostInternetScsiHba) {
- // just finding an instance of HostInternetScsiHba means that we have found at least one configured iSCSI HBA
- // at least one iSCSI HBA must be configured before a CloudStack user can use this host for iSCSI storage
- iScsiHbaConfigured = true;
-
- final String iScsiHbaDevice = hba.getDevice();
-
- final HostStorageSystemMO hss = hostStorageSystem;
-
- executorService.submit(new Thread() {
- @Override
- public void run() {
- try {
- hss.rescanHba(iScsiHbaDevice);
- hss.rescanVmfs();
- } catch (Exception ex) {
- synchronized (exceptions) {
- exceptions.add(ex);
- }
- }
- }
- });
- }
- }
-
- if (!iScsiHbaConfigured) {
- throw new Exception("An iSCSI HBA must be configured before a host can use iSCSI storage.");
- }
- }
-
- executorService.shutdown();
-
- if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES)) {
- throw new Exception("The system timed out before completing the task 'rescanAllHosts'.");
- }
-
- if (exceptions.size() > 0) {
- throw new Exception(exceptions.get(0).getMessage());
- }
- }
-
- private ManagedObjectReference getVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, int storagePortNumber,
- String iqn, String chapName, String chapSecret, String mutualChapName, String mutualChapSecret) throws Exception {
- VmwareContext context = getServiceContext();
- ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
- ClusterMO cluster = new ClusterMO(context, morCluster);
- List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts();
-
- HostInternetScsiHbaStaticTarget target = new HostInternetScsiHbaStaticTarget();
-
- target.setAddress(storageIpAddress);
- target.setPort(storagePortNumber);
- target.setIScsiName(iqn);
-
- if (StringUtils.isNotBlank(chapName) && StringUtils.isNotBlank(chapSecret)) {
- HostInternetScsiHbaAuthenticationProperties auth = new HostInternetScsiHbaAuthenticationProperties();
-
- String strAuthType = "chapRequired";
-
- auth.setChapAuthEnabled(true);
- auth.setChapInherited(false);
- auth.setChapAuthenticationType(strAuthType);
- auth.setChapName(chapName);
- auth.setChapSecret(chapSecret);
-
- if (StringUtils.isNotBlank(mutualChapName) && StringUtils.isNotBlank(mutualChapSecret)) {
- auth.setMutualChapInherited(false);
- auth.setMutualChapAuthenticationType(strAuthType);
- auth.setMutualChapName(mutualChapName);
- auth.setMutualChapSecret(mutualChapSecret);
- }
-
- target.setAuthenticationProperties(auth);
- }
-
- final List<HostInternetScsiHbaStaticTarget> lstTargets = new ArrayList<HostInternetScsiHbaStaticTarget>();
-
- lstTargets.add(target);
-
- addRemoveInternetScsiTargetsToAllHosts(true, lstTargets, lstHosts);
-
- rescanAllHosts(lstHosts);
-
- HostMO host = new HostMO(context, lstHosts.get(0).first());
- HostDatastoreSystemMO hostDatastoreSystem = host.getHostDatastoreSystemMO();
-
- ManagedObjectReference morDs = hostDatastoreSystem.findDatastoreByName(datastoreName);
-
- if (morDs != null) {
- return morDs;
- }
-
- rescanAllHosts(lstHosts);
-
- HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
- List<HostScsiDisk> lstHostScsiDisks = hostDatastoreSystem.queryAvailableDisksForVmfs();
-
- HostScsiDisk hostScsiDisk = getHostScsiDisk(hostStorageSystem.getStorageDeviceInfo().getScsiTopology(), lstHostScsiDisks, iqn);
-
- if (hostScsiDisk == null) {
- // check to see if the datastore actually does exist already
- morDs = hostDatastoreSystem.findDatastoreByName(datastoreName);
-
- if (morDs != null) {
- return morDs;
- }
-
- throw new Exception("A relevant SCSI disk could not be located to use to create a datastore.");
- }
-
- morDs = hostDatastoreSystem.createVmfsDatastore(datastoreName, hostScsiDisk);
-
- if (morDs != null) {
- rescanAllHosts(lstHosts);
-
- return morDs;
- }
-
- throw new Exception("Unable to create a datastore");
- }
-
- // the purpose of this method is to find the HostScsiDisk in the passed-in array that exists (if any) because
- // we added the static iqn to an iSCSI HBA
- private static HostScsiDisk getHostScsiDisk(HostScsiTopology hst, List<HostScsiDisk> lstHostScsiDisks, String iqn) {
- for (HostScsiTopologyInterface adapter : hst.getAdapter()) {
- if (adapter.getTarget() != null) {
- for (HostScsiTopologyTarget target : adapter.getTarget()) {
- if (target.getTransport() instanceof HostInternetScsiTargetTransport) {
- String iScsiName = ((HostInternetScsiTargetTransport)target.getTransport()).getIScsiName();
-
- if (iqn.equals(iScsiName)) {
- for (HostScsiDisk hostScsiDisk : lstHostScsiDisks) {
- for (HostScsiTopologyLun hstl : target.getLun()) {
- if (hstl.getScsiLun().contains(hostScsiDisk.getUuid())) {
- return hostScsiDisk;
- }
- }
- }
- }
- }
- }
- }
- }
-
- return null;
- }
-
- private void deleteVmfsDatastore(VmwareHypervisorHost hyperHost, String volumeUuid, String storageIpAddress, int storagePortNumber, String iqn) throws Exception {
- // hyperHost.unmountDatastore(volumeUuid);
-
- VmwareContext context = getServiceContext();
- ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
- ClusterMO cluster = new ClusterMO(context, morCluster);
- List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts();
-
- HostInternetScsiHbaStaticTarget target = new HostInternetScsiHbaStaticTarget();
-
- target.setAddress(storageIpAddress);
- target.setPort(storagePortNumber);
- target.setIScsiName(iqn);
-
- final List<HostInternetScsiHbaStaticTarget> lstTargets = new ArrayList<HostInternetScsiHbaStaticTarget>();
-
- lstTargets.add(target);
-
- addRemoveInternetScsiTargetsToAllHosts(false, lstTargets, lstHosts);
-
- rescanAllHosts(lstHosts);
- }
-
protected Answer execute(AttachIsoCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource AttachIsoCommand: " + _gson.toJson(cmd));
@@ -4530,195 +4003,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
- private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo, String vmdkName, ManagedObjectReference morDatastore,
- ManagedObjectReference morPool) throws Exception {
-
- if (dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
- dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
-
- s_logger.info("creating full clone from template");
- if (!vmTemplate.createFullClone(vmdkName, dcMo.getVmFolder(), morPool, morDatastore)) {
- String msg = "Unable to create full clone from the template";
- s_logger.error(msg);
- throw new Exception(msg);
- }
-
- // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
- // to move files
- s_logger.info("Move volume out of volume-wrapper VM ");
- dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName), dcMo.getMor(), dsMo.getMor(),
- String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
-
- dsMo.moveDatastoreFile(String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmdkName, vmdkName), dcMo.getMor(), dsMo.getMor(),
- String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
-
- return true;
- }
-
- private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo, String vmdkName, ManagedObjectReference morDatastore,
- ManagedObjectReference morPool) throws Exception {
-
- ManagedObjectReference morBaseSnapshot = vmTemplate.getSnapshotMor("cloud.template.base");
- if (morBaseSnapshot == null) {
- String msg = "Unable to find template base snapshot, invalid template";
- s_logger.error(msg);
- throw new Exception(msg);
- }
-
- if (dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
- dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
-
- s_logger.info("creating linked clone from template");
- if (!vmTemplate.createLinkedClone(vmdkName, morBaseSnapshot, dcMo.getVmFolder(), morPool, morDatastore)) {
- String msg = "Unable to clone from the template";
- s_logger.error(msg);
- throw new Exception(msg);
- }
-
- // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
- // to move files
- s_logger.info("Move volume out of volume-wrapper VM ");
- dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName), dcMo.getMor(), dsMo.getMor(),
- String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
-
- dsMo.moveDatastoreFile(String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmdkName, vmdkName), dcMo.getMor(), dsMo.getMor(),
- String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
-
- return true;
- }
-
- @Override
- public CreateAnswer execute(CreateCommand cmd) {
- if (s_logger.isInfoEnabled()) {
- s_logger.info("Executing resource CreateCommand: " + _gson.toJson(cmd));
- }
-
- StorageFilerTO pool = cmd.getPool();
- DiskProfile dskch = cmd.getDiskCharacteristics();
-
- try {
- VmwareContext context = getServiceContext();
- VmwareHypervisorHost hyperHost = getHyperHost(context);
- DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
-
- ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, pool.getUuid());
- if (morDatastore == null)
- throw new Exception("Unable to find datastore in vSphere");
-
- DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
-
- if (dskch.getType() == Volume.Type.ROOT) {
- // attach volume id to make the name unique
- String vmdkName = dskch.getName() + "-" + dskch.getVolumeId();
- if (cmd.getTemplateUrl() == null) {
- // create a root volume for blank VM
- String dummyVmName = getWorkerName(context, cmd, 0);
- VirtualMachineMO vmMo = null;
-
- try {
- vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
- if (vmMo == null) {
- throw new Exception("Unable to create a dummy VM for volume creation");
- }
-
- String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
-
- s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
- VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
- vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dskch.getSize()), morDatastore, -1);
- vmMo.detachDisk(volumeDatastorePath, false);
-
- VolumeTO vol =
- new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), dskch.getName(), pool.getPath(), vmdkName, dskch.getSize(),
- null);
- return new CreateAnswer(cmd, vol);
- } finally {
-
- s_logger.info("Destroy dummy VM after volume creation");
- if (vmMo != null) {
- s_logger.warn("Unable to destroy a null VM ManagedObjectReference");
- vmMo.detachAllDisks();
- vmMo.destroy();
- }
- }
- } else {
- VirtualMachineMO vmTemplate = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(cmd.getTemplateUrl()), true);
- if (vmTemplate == null) {
- s_logger.warn("Template host in vSphere is not in connected state, request template reload");
- return new CreateAnswer(cmd, "Template host in vSphere is not in connected state, request template reload", true);
- }
-
- ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
- ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
- if (!_fullCloneFlag) {
- createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
- } else {
- createVMFullClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
- }
-
- VirtualMachineMO vmMo = new ClusterMO(context, morCluster).findVmOnHyperHost(vmdkName);
- assert (vmMo != null);
-
- s_logger.info("detach disks from volume-wrapper VM " + vmdkName);
- vmMo.detachAllDisks();
-
- s_logger.info("destroy volume-wrapper VM " + vmdkName);
- vmMo.destroy();
-
- String srcFile = String.format("[%s] %s/", dsMo.getName(), vmdkName);
- dsMo.deleteFile(srcFile, dcMo.getMor(), true);
-
- VolumeTO vol =
- new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), dskch.getName(), pool.getPath(), vmdkName, dskch.getSize(), null);
- return new CreateAnswer(cmd, vol);
- }
- } else {
- // create data volume
- VirtualMachineMO vmMo = null;
- String volumeUuid = UUID.randomUUID().toString().replace("-", "");
- String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
- String dummyVmName = getWorkerName(context, cmd, 0);
- try {
- vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
- if (vmMo == null) {
- throw new Exception("Unable to create a dummy VM for volume creation");
- }
-
- // s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
- VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
-
- vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dskch.getSize()), morDatastore, vmMo.getScsiDeviceControllerKey());
- vmMo.detachDisk(volumeDatastorePath, false);
-
- VolumeTO vol =
- new VolumeTO(cmd.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), dskch.getName(), pool.getPath(), volumeUuid, dskch.getSize(),
- null);
- return new CreateAnswer(cmd, vol);
- } finally {
- s_logger.info("Destroy dummy VM after volume creation");
- if (vmMo != null) {
- s_logger.warn("Unable to destroy a null VM ManagedObjectReference");
- vmMo.detachAllDisks();
- vmMo.destroy();
- }
- }
- }
- } catch (Throwable e) {
- if (e instanceof RemoteException) {
- s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
- invalidateServiceContext();
- }
-
- String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
- s_logger.error(msg, e);
- return new CreateAnswer(cmd, new Exception(e));
- }
- }
-
- private static int getMBsFromBytes(long bytes) {
- return (int)(bytes / (1024L * 1024L));
- }
-
@Override
public void disconnected() {
}
@@ -5751,9 +5035,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
value = (String)params.get("scripts.timeout");
int timeout = NumbersUtil.parseInt(value, 1440) * 1000;
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
- VmwareStorageProcessor storageProcessor =
- new VmwareStorageProcessor((VmwareHostService)this, _fullCloneFlag, (VmwareStorageMount)mgr, timeout, this, _shutdownWaitMs, null);
- storageHandler = new VmwareStorageSubsystemCommandHandler(storageProcessor);
+ _storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, _fullCloneFlag, (VmwareStorageMount)mgr, timeout, this, _shutdownWaitMs, null);
+ storageHandler = new VmwareStorageSubsystemCommandHandler(_storageProcessor);
_vrResource = new VirtualRoutingResource(this);
if (!_vrResource.configure(name, params)) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d40c465a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
----------------------------------------------------------------------
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 96c6d32..f633774 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
@@ -18,8 +18,6 @@ package com.cloud.storage.resource;
import java.util.List;
-import javax.naming.OperationNotSupportedException;
-
import org.apache.log4j.Logger;
import com.google.gson.Gson;
@@ -313,28 +311,4 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
public String getMountPoint(String storageUrl) {
return _resource.getRootDir(storageUrl);
}
-
- @Override
- public ManagedObjectReference prepareManagedDatastore(VmwareHypervisorHost hyperHost, String iScsiName,
- String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
- String chapTargetUsername, String chapTargetSecret) throws Exception {
- throw new OperationNotSupportedException();
- }
-
- @Override
- public ManagedObjectReference prepareManagedStorage(VmwareHypervisorHost hyperHost, String iScsiName,
- String storageHost, int storagePort, String volumeName, String chapInitiatorUsername, String chapInitiatorSecret,
- String chapTargetUsername, String chapTargetSecret, long size, Command cmd) throws Exception {
- throw new OperationNotSupportedException();
- }
-
- @Override
- public void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception {
- throw new OperationNotSupportedException();
- }
-
- @Override
- public void removeManagedTargetsFromCluster(List<String> managedIqns) throws Exception {
- throw new OperationNotSupportedException();
- }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d40c465a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
----------------------------------------------------------------------
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 3d3aa1b..fd7520e 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -27,11 +27,24 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.google.gson.Gson;
+import com.vmware.vim25.HostHostBusAdapter;
+import com.vmware.vim25.HostInternetScsiHba;
+import com.vmware.vim25.HostInternetScsiHbaAuthenticationProperties;
+import com.vmware.vim25.HostInternetScsiHbaStaticTarget;
+import com.vmware.vim25.HostInternetScsiTargetTransport;
+import com.vmware.vim25.HostScsiDisk;
+import com.vmware.vim25.HostScsiTopology;
+import com.vmware.vim25.HostScsiTopologyInterface;
+import com.vmware.vim25.HostScsiTopologyLun;
+import com.vmware.vim25.HostScsiTopologyTarget;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.VirtualDisk;
import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo;
@@ -64,7 +77,9 @@ import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
import com.cloud.hypervisor.vmware.mo.DatastoreFile;
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
+import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO;
import com.cloud.hypervisor.vmware.mo.HostMO;
+import com.cloud.hypervisor.vmware.mo.HostStorageSystemMO;
import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
import com.cloud.hypervisor.vmware.mo.NetworkDetails;
import com.cloud.hypervisor.vmware.mo.VirtualMachineDiskInfo;
@@ -82,6 +97,7 @@ import com.cloud.storage.Volume;
import com.cloud.storage.template.OVAProcessor;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
+import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import com.cloud.vm.VirtualMachine.State;
@@ -262,7 +278,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
final ManagedObjectReference morDs;
if (managed) {
- morDs = hostService.prepareManagedDatastore(hyperHost, managedStoragePoolName, storageHost, storagePort,
+ morDs = prepareManagedDatastore(context, hyperHost, managedStoragePoolName, storageHost, storagePort,
chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
}
else {
@@ -319,32 +335,67 @@ public class VmwareStorageProcessor implements StorageProcessor {
private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo, String vmdkName, ManagedObjectReference morDatastore,
ManagedObjectReference morPool) throws Exception {
-
ManagedObjectReference morBaseSnapshot = vmTemplate.getSnapshotMor("cloud.template.base");
+
if (morBaseSnapshot == null) {
String msg = "Unable to find template base snapshot, invalid template";
+
s_logger.error(msg);
+
throw new Exception(msg);
}
+ if (dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName)) {
+ dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
+ }
+
s_logger.info("creating linked clone from template");
+
if (!vmTemplate.createLinkedClone(vmdkName, morBaseSnapshot, dcMo.getVmFolder(), morPool, morDatastore)) {
String msg = "Unable to clone from the template";
+
s_logger.error(msg);
+
throw new Exception(msg);
}
+
+ // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know to move files
+ s_logger.info("Move volume out of volume-wrapper VM ");
+
+ dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName), dcMo.getMor(), dsMo.getMor(),
+ String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+
+ dsMo.moveDatastoreFile(String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmdkName, vmdkName), dcMo.getMor(), dsMo.getMor(),
+ String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+
return true;
}
private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo, String vmdkName, ManagedObjectReference morDatastore,
ManagedObjectReference morPool) throws Exception {
+ if (dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName)) {
+ dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
+ }
s_logger.info("creating full clone from template");
+
if (!vmTemplate.createFullClone(vmdkName, dcMo.getVmFolder(), morPool, morDatastore)) {
String msg = "Unable to create full clone from the template";
+
s_logger.error(msg);
+
throw new Exception(msg);
}
+
+ // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know to move files
+ s_logger.info("Move volume out of volume-wrapper VM ");
+
+ dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName), dcMo.getMor(), dsMo.getMor(),
+ String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+
+ dsMo.moveDatastoreFile(String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmdkName, vmdkName), dcMo.getMor(), dsMo.getMor(),
+ String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+
return true;
}
@@ -1241,7 +1292,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData();
DataStoreTO primaryStore = volumeTO.getDataStore();
try {
- VmwareHypervisorHost hyperHost = hostService.getHyperHost(hostService.getServiceContext(null), null);
+ VmwareContext context = hostService.getServiceContext(null);
+ VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
if (vmMo == null) {
String msg = "Unable to find the VM to execute AttachVolumeCommand, vmName: " + vmName;
@@ -1254,7 +1306,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
if (isAttach && isManaged) {
Map<String, String> details = disk.getDetails();
- morDs = hostService.prepareManagedStorage(hyperHost, iScsiName, storageHost, storagePort, null,
+ morDs = prepareManagedStorage(context, hyperHost, iScsiName, storageHost, storagePort, null,
details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET),
details.get(DiskTO.CHAP_TARGET_USERNAME), details.get(DiskTO.CHAP_TARGET_SECRET),
volumeTO.getSize(), cmd);
@@ -1269,7 +1321,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
throw new Exception(msg);
}
- DatastoreMO dsMo = new DatastoreMO(hostService.getServiceContext(null), morDs);
+ DatastoreMO dsMo = new DatastoreMO(context, morDs);
String datastoreVolumePath;
if (isAttach) {
@@ -1301,7 +1353,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
vmMo.detachDisk(datastoreVolumePath, false);
if (isManaged) {
- hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort);
+ handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort);
} else {
VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, volumeTO.getPath());
}
@@ -1340,7 +1392,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
private Answer attachIso(DiskTO disk, boolean isAttach, String vmName) {
try {
- VmwareHypervisorHost hyperHost = hostService.getHyperHost(hostService.getServiceContext(null), null);
+ VmwareContext context = hostService.getServiceContext(null);
+ VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
if (vmMo == null) {
String msg = "Unable to find VM in vSphere to execute AttachIsoCommand, vmName: " + vmName;
@@ -1390,7 +1443,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
// TODO, check if iso is already attached, or if there is a previous
// attachment
- DatastoreMO secondaryDsMo = new DatastoreMO(hostService.getServiceContext(null), morSecondaryDs);
+ DatastoreMO secondaryDsMo = new DatastoreMO(context, morSecondaryDs);
String storeName = secondaryDsMo.getName();
String isoDatastorePath = String.format("[%s] %s/%s", storeName, isoStorePathFromRoot, isoFileName);
@@ -1595,7 +1648,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
// this.hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort);
if (managedIqns != null && !managedIqns.isEmpty()) {
- hostService.removeManagedTargetsFromCluster(managedIqns);
+ removeManagedTargetsFromCluster(managedIqns);
}
for (NetworkDetails netDetails : networks) {
@@ -1648,6 +1701,345 @@ public class VmwareStorageProcessor implements StorageProcessor {
}
}
+ private ManagedObjectReference prepareManagedDatastore(VmwareContext context, VmwareHypervisorHost hyperHost, String iScsiName,
+ String storageHost, int storagePort, String chapInitiatorUsername, String chapInitiatorSecret,
+ String chapTargetUsername, String chapTargetSecret) throws Exception {
+ return getVmfsDatastore(context, hyperHost, VmwareResource.getDatastoreName(iScsiName), storageHost, storagePort,
+ trimIqn(iScsiName), chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
+ }
+
+ private ManagedObjectReference getVmfsDatastore(VmwareContext context, VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, int storagePortNumber,
+ String iqn, String chapName, String chapSecret, String mutualChapName, String mutualChapSecret) throws Exception {
+ ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
+ ClusterMO cluster = new ClusterMO(context, morCluster);
+ List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts();
+
+ HostInternetScsiHbaStaticTarget target = new HostInternetScsiHbaStaticTarget();
+
+ target.setAddress(storageIpAddress);
+ target.setPort(storagePortNumber);
+ target.setIScsiName(iqn);
+
+ if (StringUtils.isNotBlank(chapName) && StringUtils.isNotBlank(chapSecret)) {
+ HostInternetScsiHbaAuthenticationProperties auth = new HostInternetScsiHbaAuthenticationProperties();
+
+ String strAuthType = "chapRequired";
+
+ auth.setChapAuthEnabled(true);
+ auth.setChapInherited(false);
+ auth.setChapAuthenticationType(strAuthType);
+ auth.setChapName(chapName);
+ auth.setChapSecret(chapSecret);
+
+ if (StringUtils.isNotBlank(mutualChapName) && StringUtils.isNotBlank(mutualChapSecret)) {
+ auth.setMutualChapInherited(false);
+ auth.setMutualChapAuthenticationType(strAuthType);
+ auth.setMutualChapName(mutualChapName);
+ auth.setMutualChapSecret(mutualChapSecret);
+ }
+
+ target.setAuthenticationProperties(auth);
+ }
+
+ final List<HostInternetScsiHbaStaticTarget> lstTargets = new ArrayList<HostInternetScsiHbaStaticTarget>();
+
+ lstTargets.add(target);
+
+ addRemoveInternetScsiTargetsToAllHosts(context, true, lstTargets, lstHosts);
+
+ rescanAllHosts(context, lstHosts);
+
+ HostMO host = new HostMO(context, lstHosts.get(0).first());
+ HostDatastoreSystemMO hostDatastoreSystem = host.getHostDatastoreSystemMO();
+
+ ManagedObjectReference morDs = hostDatastoreSystem.findDatastoreByName(datastoreName);
+
+ if (morDs != null) {
+ return morDs;
+ }
+
+ rescanAllHosts(context, lstHosts);
+
+ HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
+ List<HostScsiDisk> lstHostScsiDisks = hostDatastoreSystem.queryAvailableDisksForVmfs();
+
+ HostScsiDisk hostScsiDisk = getHostScsiDisk(hostStorageSystem.getStorageDeviceInfo().getScsiTopology(), lstHostScsiDisks, iqn);
+
+ if (hostScsiDisk == null) {
+ // check to see if the datastore actually does exist already
+ morDs = hostDatastoreSystem.findDatastoreByName(datastoreName);
+
+ if (morDs != null) {
+ return morDs;
+ }
+
+ throw new Exception("A relevant SCSI disk could not be located to use to create a datastore.");
+ }
+
+ morDs = hostDatastoreSystem.createVmfsDatastore(datastoreName, hostScsiDisk);
+
+ if (morDs != null) {
+ rescanAllHosts(context, lstHosts);
+
+ return morDs;
+ }
+
+ throw new Exception("Unable to create a datastore");
+ }
+
+ // the purpose of this method is to find the HostScsiDisk in the passed-in array that exists (if any) because
+ // we added the static iqn to an iSCSI HBA
+ private static HostScsiDisk getHostScsiDisk(HostScsiTopology hst, List<HostScsiDisk> lstHostScsiDisks, String iqn) {
+ for (HostScsiTopologyInterface adapter : hst.getAdapter()) {
+ if (adapter.getTarget() != null) {
+ for (HostScsiTopologyTarget target : adapter.getTarget()) {
+ if (target.getTransport() instanceof HostInternetScsiTargetTransport) {
+ String iScsiName = ((HostInternetScsiTargetTransport)target.getTransport()).getIScsiName();
+
+ if (iqn.equals(iScsiName)) {
+ for (HostScsiDisk hostScsiDisk : lstHostScsiDisks) {
+ for (HostScsiTopologyLun hstl : target.getLun()) {
+ if (hstl.getScsiLun().contains(hostScsiDisk.getUuid())) {
+ return hostScsiDisk;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private void deleteVmfsDatastore(VmwareHypervisorHost hyperHost, String volumeUuid, String storageIpAddress, int storagePortNumber, String iqn) throws Exception {
+ // hyperHost.unmountDatastore(volumeUuid);
+
+ VmwareContext context = hostService.getServiceContext(null);
+ ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
+ ClusterMO cluster = new ClusterMO(context, morCluster);
+ List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts();
+
+ HostInternetScsiHbaStaticTarget target = new HostInternetScsiHbaStaticTarget();
+
+ target.setAddress(storageIpAddress);
+ target.setPort(storagePortNumber);
+ target.setIScsiName(iqn);
+
+ final List<HostInternetScsiHbaStaticTarget> lstTargets = new ArrayList<HostInternetScsiHbaStaticTarget>();
+
+ lstTargets.add(target);
+
+ addRemoveInternetScsiTargetsToAllHosts(context, false, lstTargets, lstHosts);
+
+ rescanAllHosts(context, lstHosts);
+ }
+
+ private void createVmdk(Command cmd, DatastoreMO dsMo, String vmdkDatastorePath, Long volumeSize) throws Exception {
+ VmwareContext context = hostService.getServiceContext(null);
+ VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
+
+ String dummyVmName = hostService.getWorkerName(context, cmd, 0);
+
+ VirtualMachineMO vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
+
+ if (vmMo == null) {
+ throw new Exception("Unable to create a dummy VM for volume creation");
+ }
+
+ Long volumeSizeToUse = volumeSize < dsMo.getSummary().getFreeSpace() ? volumeSize : dsMo.getSummary().getFreeSpace();
+
+ vmMo.createDisk(vmdkDatastorePath, getMBsFromBytes(volumeSizeToUse), dsMo.getMor(), vmMo.getScsiDeviceControllerKey());
+ vmMo.detachDisk(vmdkDatastorePath, false);
+ vmMo.destroy();
+ }
+
+ private static int getMBsFromBytes(long bytes) {
+ return (int)(bytes / (1024L * 1024L));
+ }
+
+ private void addRemoveInternetScsiTargetsToAllHosts(VmwareContext context, final boolean add, final List<HostInternetScsiHbaStaticTarget> lstTargets,
+ List<Pair<ManagedObjectReference, String>> lstHosts) throws Exception {
+ ExecutorService executorService = Executors.newFixedThreadPool(lstHosts.size());
+
+ final List<Exception> exceptions = new ArrayList<Exception>();
+
+ for (Pair<ManagedObjectReference, String> hostPair : lstHosts) {
+ HostMO host = new HostMO(context, hostPair.first());
+ HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
+
+ boolean iScsiHbaConfigured = false;
+
+ for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) {
+ if (hba instanceof HostInternetScsiHba) {
+ // just finding an instance of HostInternetScsiHba means that we have found at least one configured iSCSI HBA
+ // at least one iSCSI HBA must be configured before a CloudStack user can use this host for iSCSI storage
+ iScsiHbaConfigured = true;
+
+ final String iScsiHbaDevice = hba.getDevice();
+
+ final HostStorageSystemMO hss = hostStorageSystem;
+
+ executorService.submit(new Thread() {
+ @Override
+ public void run() {
+ try {
+ if (add) {
+ hss.addInternetScsiStaticTargets(iScsiHbaDevice, lstTargets);
+ } else {
+ hss.removeInternetScsiStaticTargets(iScsiHbaDevice, lstTargets);
+ }
+
+ hss.rescanHba(iScsiHbaDevice);
+ hss.rescanVmfs();
+ } catch (Exception ex) {
+ synchronized (exceptions) {
+ exceptions.add(ex);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ if (!iScsiHbaConfigured) {
+ throw new Exception("An iSCSI HBA must be configured before a host can use iSCSI storage.");
+ }
+ }
+
+ executorService.shutdown();
+
+ if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES)) {
+ throw new Exception("The system timed out before completing the task 'rescanAllHosts'.");
+ }
+
+ if (exceptions.size() > 0) {
+ throw new Exception(exceptions.get(0).getMessage());
+ }
+ }
+
+ private void rescanAllHosts(VmwareContext context, List<Pair<ManagedObjectReference, String>> lstHosts) throws Exception {
+ ExecutorService executorService = Executors.newFixedThreadPool(lstHosts.size());
+
+ final List<Exception> exceptions = new ArrayList<Exception>();
+
+ for (Pair<ManagedObjectReference, String> hostPair : lstHosts) {
+ HostMO host = new HostMO(context, hostPair.first());
+ HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
+
+ boolean iScsiHbaConfigured = false;
+
+ for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) {
+ if (hba instanceof HostInternetScsiHba) {
+ // just finding an instance of HostInternetScsiHba means that we have found at least one configured iSCSI HBA
+ // at least one iSCSI HBA must be configured before a CloudStack user can use this host for iSCSI storage
+ iScsiHbaConfigured = true;
+
+ final String iScsiHbaDevice = hba.getDevice();
+
+ final HostStorageSystemMO hss = hostStorageSystem;
+
+ executorService.submit(new Thread() {
+ @Override
+ public void run() {
+ try {
+ hss.rescanHba(iScsiHbaDevice);
+ hss.rescanVmfs();
+ } catch (Exception ex) {
+ synchronized (exceptions) {
+ exceptions.add(ex);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ if (!iScsiHbaConfigured) {
+ throw new Exception("An iSCSI HBA must be configured before a host can use iSCSI storage.");
+ }
+ }
+
+ executorService.shutdown();
+
+ if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES)) {
+ throw new Exception("The system timed out before completing the task 'rescanAllHosts'.");
+ }
+
+ if (exceptions.size() > 0) {
+ throw new Exception(exceptions.get(0).getMessage());
+ }
+ }
+
+ private static String trimIqn(String iqn) {
+ String[] tmp = iqn.split("/");
+
+ if (tmp.length != 3) {
+ String msg = "Wrong format for iScsi path: " + iqn + ". It should be formatted as '/targetIQN/LUN'.";
+
+ s_logger.warn(msg);
+
+ throw new CloudRuntimeException(msg);
+ }
+
+ return tmp[1].trim();
+ }
+
+ public ManagedObjectReference prepareManagedStorage(VmwareContext context, VmwareHypervisorHost hyperHost, String iScsiName,
+ String storageHost, int storagePort, String volumeName, String chapInitiatorUsername, String chapInitiatorSecret,
+ String chapTargetUsername, String chapTargetSecret, long size, Command cmd) throws Exception {
+ ManagedObjectReference morDs = prepareManagedDatastore(context, hyperHost, iScsiName, storageHost, storagePort,
+ chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
+
+ DatastoreMO dsMo = new DatastoreMO(hostService.getServiceContext(null), morDs);
+
+ String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeName != null ? volumeName : dsMo.getName());
+
+ if (!dsMo.fileExists(volumeDatastorePath)) {
+ createVmdk(cmd, dsMo, volumeDatastorePath, size);
+ }
+
+ return morDs;
+ }
+
+ private void handleDatastoreAndVmdkDetach(String iqn, String storageHost, int storagePort) throws Exception {
+ VmwareContext context = hostService.getServiceContext(null);
+ VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
+
+ deleteVmfsDatastore(hyperHost, VmwareResource.getDatastoreName(iqn), storageHost, storagePort, trimIqn(iqn));
+ }
+
+ private void removeManagedTargetsFromCluster(List<String> iqns) throws Exception {
+ List<HostInternetScsiHbaStaticTarget> lstManagedTargets = new ArrayList<HostInternetScsiHbaStaticTarget>();
+
+ VmwareContext context = hostService.getServiceContext(null);
+ VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
+ 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(context, false, lstManagedTargets, lstHosts);
+
+ rescanAllHosts(context, lstHosts);
+ }
+
private List<String> getManagedIqnsFromVirtualDisks(List<VirtualDisk> virtualDisks) {
List<String> managedIqns = new ArrayList<String>();