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/01/10 05:37:17 UTC
git commit: updated refs/heads/master to ae35782
Updated Branches:
refs/heads/master bc1eec9f7 -> ae35782cc
Merge from 4.3: CLOUDSTACK-5662: XenServer can't discover iSCSI targets with different credentials
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/ae35782c
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ae35782c
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ae35782c
Branch: refs/heads/master
Commit: ae35782ccdc208c3b2952a1250b8164f86238f56
Parents: bc1eec9
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Thu Jan 9 21:36:34 2014 -0700
Committer: Mike Tutkowski <mi...@solidfire.com>
Committed: Thu Jan 9 21:36:34 2014 -0700
----------------------------------------------------------------------
api/src/com/cloud/host/Host.java | 5 +
.../api/agent/test/CheckOnHostCommandTest.java | 5 +-
.../api/storage/PrimaryDataStoreDriver.java | 5 +
.../subsystem/api/storage/VolumeService.java | 4 +
.../test/FakePrimaryDataStoreDriver.java | 14 +-
.../storage/volume/VolumeServiceImpl.java | 18 +
.../vmware/resource/VmwareResource.java | 51 ++-
.../CloudStackPrimaryDataStoreDriverImpl.java | 7 +
.../SamplePrimaryDataStoreDriverImpl.java | 7 +
.../driver/SolidfirePrimaryDataStoreDriver.java | 236 +++++++++-
.../storage/datastore/util/SolidFireUtil.java | 459 ++++++++++++++-----
.../com/cloud/storage/VolumeApiServiceImpl.java | 41 +-
.../com/cloud/hypervisor/vmware/mo/HostMO.java | 4 +-
13 files changed, 691 insertions(+), 165 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/api/src/com/cloud/host/Host.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/host/Host.java b/api/src/com/cloud/host/Host.java
index 9d81125..689ed12 100755
--- a/api/src/com/cloud/host/Host.java
+++ b/api/src/com/cloud/host/Host.java
@@ -79,6 +79,11 @@ public interface Host extends StateObject<Status>, Identity, InternalIdentity {
String getPrivateIpAddress();
/**
+ * @return the ip address of the host.
+ */
+ String getStorageUrl();
+
+ /**
* @return the ip address of the host attached to the storage network.
*/
String getStorageIpAddress();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java
----------------------------------------------------------------------
diff --git a/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java
index d266eb3..9edbf10 100644
--- a/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java
+++ b/core/test/org/apache/cloudstack/api/agent/test/CheckOnHostCommandTest.java
@@ -81,7 +81,10 @@ public class CheckOnHostCommandTest {
return "10.1.1.1";
};
- @Override
+ public String getStorageUrl() {
+ return null;
+ }
+
public String getStorageIpAddress() {
return "10.1.1.2";
};
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
index 369ee9c..c4dfc5c 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
@@ -21,12 +21,17 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
+import com.cloud.host.Host;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
public interface PrimaryDataStoreDriver extends DataStoreDriver {
public ChapInfo getChapInfo(VolumeInfo volumeInfo);
+ public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore);
+
+ public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore);
+
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool);
public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
index bcc4e7f..3f676ae 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
@@ -44,6 +44,10 @@ public interface VolumeService {
ChapInfo getChapInfo(VolumeInfo volumeInfo, DataStore dataStore);
+ boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore);
+
+ void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore);
+
/**
* Creates the volume based on the given criteria
*
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java
index dad6408..266baa7 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/FakePrimaryDataStoreDriver.java
@@ -36,6 +36,7 @@ import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
+import com.cloud.host.Host;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
@@ -43,11 +44,22 @@ public class FakePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
boolean snapshotResult = true;
@Override
+ public Map<String, String> getCapabilities() {
+ return null;
+ }
+
+ @Override
public ChapInfo getChapInfo(VolumeInfo volumeInfo) {
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return null; // To change body of implemented methods, use File | Settings | File Templates.
}
@Override
+ public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { return false; }
+
+ @Override
+ public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {}
+
+ @Override
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
return volume.getSize();
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
index c9d7fab..ac507cf 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
@@ -158,6 +158,24 @@ public class VolumeServiceImpl implements VolumeService {
return null;
}
+ public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {
+ DataStoreDriver dataStoreDriver = dataStore.getDriver();
+
+ if (dataStoreDriver instanceof PrimaryDataStoreDriver) {
+ return ((PrimaryDataStoreDriver)dataStoreDriver).connectVolumeToHost(volumeInfo, host, dataStore);
+ }
+
+ return false;
+ }
+
+ public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {
+ DataStoreDriver dataStoreDriver = dataStore.getDriver();
+
+ if (dataStoreDriver instanceof PrimaryDataStoreDriver) {
+ ((PrimaryDataStoreDriver)dataStoreDriver).disconnectVolumeFromHost(volumeInfo, host, dataStore);
+ }
+ }
+
@Override
public AsyncCallFuture<VolumeApiResult> createVolumeAsync(VolumeInfo volume, DataStore dataStore) {
AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/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 c1d8bac..4aa6f27 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
@@ -4800,22 +4800,26 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
target.setPort(storagePortNumber);
target.setIScsiName(iqn);
- HostInternetScsiHbaAuthenticationProperties auth = new HostInternetScsiHbaAuthenticationProperties();
+ if (StringUtils.isNotBlank(chapName) && StringUtils.isNotBlank(chapSecret)) {
+ HostInternetScsiHbaAuthenticationProperties auth = new HostInternetScsiHbaAuthenticationProperties();
- String strAuthType = "chapRequired";
+ String strAuthType = "chapRequired";
- auth.setChapAuthEnabled(true);
- auth.setChapInherited(false);
- auth.setChapAuthenticationType(strAuthType);
- auth.setChapName(chapName);
- auth.setChapSecret(chapSecret);
+ auth.setChapAuthEnabled(true);
+ auth.setChapInherited(false);
+ auth.setChapAuthenticationType(strAuthType);
+ auth.setChapName(chapName);
+ auth.setChapSecret(chapSecret);
- auth.setMutualChapInherited(false);
- auth.setMutualChapAuthenticationType(strAuthType);
- auth.setMutualChapName(mutualChapName);
- auth.setMutualChapSecret(mutualChapSecret);
+ if (StringUtils.isNotBlank(mutualChapName) && StringUtils.isNotBlank(mutualChapSecret)) {
+ auth.setMutualChapInherited(false);
+ auth.setMutualChapAuthenticationType(strAuthType);
+ auth.setMutualChapName(mutualChapName);
+ auth.setMutualChapSecret(mutualChapSecret);
+ }
- target.setAuthenticationProperties(auth);
+ target.setAuthenticationProperties(auth);
+ }
final List<HostInternetScsiHbaStaticTarget> lstTargets = new ArrayList<HostInternetScsiHbaStaticTarget>();
@@ -6052,11 +6056,34 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
cmd.setName(_url);
cmd.setGuid(_guid);
cmd.setDataCenter(_dcId);
+ cmd.setIqn(getIqn());
cmd.setPod(_pod);
cmd.setCluster(_cluster);
cmd.setVersion(VmwareResource.class.getPackage().getImplementationVersion());
}
+ private String getIqn() {
+ try {
+ VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext());
+
+ if (hyperHost instanceof HostMO) {
+ HostMO host = (HostMO)hyperHost;
+ HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
+
+ for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) {
+ if (hba instanceof HostInternetScsiHba) {
+ return ((HostInternetScsiHba)hba).getIScsiName();
+ }
+ }
+ }
+ }
+ catch (Exception ex) {
+ s_logger.info("Could not locate an IQN for this host.");
+ }
+
+ return null;
+ }
+
private void fillHostHardwareInfo(VmwareContext serviceContext, StartupRoutingCommand cmd) throws RuntimeFaultFaultMsg, RemoteException, Exception {
VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext());
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
index c8e2582..ae217b6 100644
--- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
+++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
@@ -61,6 +61,7 @@ import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.configuration.Config;
import com.cloud.exception.StorageUnavailableException;
+import com.cloud.host.Host;
import com.cloud.host.dao.HostDao;
import com.cloud.storage.CreateSnapshotPayload;
import com.cloud.storage.DataStoreRole;
@@ -150,6 +151,12 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
}
@Override
+ public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { return false; }
+
+ @Override
+ public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {}
+
+ @Override
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
return volume.getSize();
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
index 4cfc097..1f9a128 100644
--- a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
+++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
@@ -42,6 +42,7 @@ import org.apache.cloudstack.storage.datastore.DataObjectManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
+import com.cloud.host.Host;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.StoragePoolHostDao;
@@ -81,6 +82,12 @@ public class SamplePrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
}
@Override
+ public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { return false; }
+
+ @Override
+ public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {}
+
+ @Override
public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
return volume.getSize();
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
index 7959af9..1212b60 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
@@ -17,8 +17,10 @@
package org.apache.cloudstack.storage.datastore.driver;
import java.text.NumberFormat;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import javax.inject.Inject;
@@ -44,7 +46,12 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
+import com.cloud.dc.ClusterDetailsVO;
+import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
@@ -55,22 +62,18 @@ import com.cloud.user.AccountDetailVO;
import com.cloud.user.AccountDetailsDao;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.exception.CloudRuntimeException;
public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
- @Inject
- private PrimaryDataStoreDao _storagePoolDao;
- @Inject
- private StoragePoolDetailsDao _storagePoolDetailsDao;
- @Inject
- private VolumeDao _volumeDao;
- @Inject
- private VolumeDetailsDao _volumeDetailsDao;
- @Inject
- private DataCenterDao _zoneDao;
- @Inject
- private AccountDao _accountDao;
- @Inject
- private AccountDetailsDao _accountDetailsDao;
+ @Inject private PrimaryDataStoreDao _storagePoolDao;
+ @Inject private StoragePoolDetailsDao _storagePoolDetailsDao;
+ @Inject private VolumeDao _volumeDao;
+ @Inject private VolumeDetailsDao _volumeDetailsDao;
+ @Inject private DataCenterDao _zoneDao;
+ @Inject private AccountDao _accountDao;
+ @Inject private AccountDetailsDao _accountDetailsDao;
+ @Inject private ClusterDetailsDao _clusterDetailsDao;
+ @Inject private HostDao _hostDao;
@Override
public Map<String, String> getCapabilities() {
@@ -149,25 +152,35 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
}
private void updateCsDbWithAccountInfo(long csAccountId, SolidFireUtil.SolidFireAccount sfAccount) {
- AccountDetailVO accountDetails = new AccountDetailVO(csAccountId, SolidFireUtil.ACCOUNT_ID, String.valueOf(sfAccount.getId()));
+ AccountDetailVO accountDetail = new AccountDetailVO(csAccountId,
+ SolidFireUtil.ACCOUNT_ID,
+ String.valueOf(sfAccount.getId()));
- _accountDetailsDao.persist(accountDetails);
+ _accountDetailsDao.persist(accountDetail);
- accountDetails = new AccountDetailVO(csAccountId, SolidFireUtil.CHAP_INITIATOR_USERNAME, String.valueOf(sfAccount.getName()));
+ accountDetail = new AccountDetailVO(csAccountId,
+ SolidFireUtil.CHAP_INITIATOR_USERNAME,
+ String.valueOf(sfAccount.getName()));
- _accountDetailsDao.persist(accountDetails);
+ _accountDetailsDao.persist(accountDetail);
- accountDetails = new AccountDetailVO(csAccountId, SolidFireUtil.CHAP_INITIATOR_SECRET, String.valueOf(sfAccount.getInitiatorSecret()));
+ accountDetail = new AccountDetailVO(csAccountId,
+ SolidFireUtil.CHAP_INITIATOR_SECRET,
+ String.valueOf(sfAccount.getInitiatorSecret()));
- _accountDetailsDao.persist(accountDetails);
+ _accountDetailsDao.persist(accountDetail);
- accountDetails = new AccountDetailVO(csAccountId, SolidFireUtil.CHAP_TARGET_USERNAME, sfAccount.getName());
+ accountDetail = new AccountDetailVO(csAccountId,
+ SolidFireUtil.CHAP_TARGET_USERNAME,
+ sfAccount.getName());
- _accountDetailsDao.persist(accountDetails);
+ _accountDetailsDao.persist(accountDetail);
- accountDetails = new AccountDetailVO(csAccountId, SolidFireUtil.CHAP_TARGET_SECRET, sfAccount.getTargetSecret());
+ accountDetail = new AccountDetailVO(csAccountId,
+ SolidFireUtil.CHAP_TARGET_SECRET,
+ sfAccount.getTargetSecret());
- _accountDetailsDao.persist(accountDetails);
+ _accountDetailsDao.persist(accountDetail);
}
private class ChapInfoImpl implements ChapInfo {
@@ -227,6 +240,179 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
return new ChapInfoImpl(chapInitiatorUsername, chapInitiatorSecret, chapTargetUsername, chapTargetSecret);
}
+ // get the VAG associated with volumeInfo's cluster, if any (ListVolumeAccessGroups)
+ // if the VAG exists
+ // update the VAG to contain all IQNs of the hosts (ModifyVolumeAccessGroup)
+ // if the ID of volumeInfo in not in the VAG, add it (ModifyVolumeAccessGroup)
+ // if the VAG doesn't exist, create it with the IQNs of the hosts and the ID of volumeInfo (CreateVolumeAccessGroup)
+ @Override
+ public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore)
+ {
+ if (volumeInfo == null || host == null || dataStore == null) {
+ return false;
+ }
+
+ long sfVolumeId = Long.parseLong(volumeInfo.getFolder());
+ long clusterId = host.getClusterId();
+ long storagePoolId = dataStore.getId();
+
+ ClusterDetailsVO clusterDetail = _clusterDetailsDao.findDetail(clusterId, getVagKey(storagePoolId));
+
+ String vagId = clusterDetail != null ? clusterDetail.getValue() : null;
+
+ List<HostVO> hosts = _hostDao.findByClusterId(clusterId);
+
+ if (!hostsSupport_iScsi(hosts)) {
+ return false;
+ }
+
+ SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);
+
+ if (vagId != null) {
+ SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
+ sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), Long.parseLong(vagId));
+
+ long[] volumeIds = getNewVolumeIds(sfVag.getVolumeIds(), sfVolumeId, true);
+
+ SolidFireUtil.modifySolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
+ sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), sfVag.getId(),
+ getIqnsFromHosts(hosts), volumeIds);
+ }
+ else {
+ long lVagId = SolidFireUtil.createSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
+ sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), "CloudStack-" + UUID.randomUUID().toString(),
+ getIqnsFromHosts(hosts), new long[] { sfVolumeId });
+
+ clusterDetail = new ClusterDetailsVO(clusterId, getVagKey(storagePoolId), String.valueOf(lVagId));
+
+ _clusterDetailsDao.persist(clusterDetail);
+ }
+
+ return true;
+ }
+
+ // get the VAG associated with volumeInfo's cluster, if any (ListVolumeAccessGroups) // might not exist if using CHAP
+ // if the VAG exists
+ // remove the ID of volumeInfo from the VAG (ModifyVolumeAccessGroup)
+ @Override
+ public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore)
+ {
+ if (volumeInfo == null || host == null || dataStore == null) {
+ return;
+ }
+
+ long sfVolumeId = Long.parseLong(volumeInfo.getFolder());
+ long clusterId = host.getClusterId();
+ long storagePoolId = dataStore.getId();
+
+ ClusterDetailsVO clusterDetail = _clusterDetailsDao.findDetail(clusterId, getVagKey(storagePoolId));
+
+ String vagId = clusterDetail != null ? clusterDetail.getValue() : null;
+
+ if (vagId != null) {
+ List<HostVO> hosts = _hostDao.findByClusterId(clusterId);
+
+ SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);
+
+ SolidFireUtil.SolidFireVag sfVag = SolidFireUtil.getSolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
+ sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), Long.parseLong(vagId));
+
+ long[] volumeIds = getNewVolumeIds(sfVag.getVolumeIds(), sfVolumeId, false);
+
+ SolidFireUtil.modifySolidFireVag(sfConnection.getManagementVip(), sfConnection.getManagementPort(),
+ sfConnection.getClusterAdminUsername(), sfConnection.getClusterAdminPassword(), sfVag.getId(),
+ getIqnsFromHosts(hosts), volumeIds);
+ }
+ }
+
+ private boolean hostsSupport_iScsi(List<HostVO> hosts) {
+ if (hosts == null || hosts.size() == 0) {
+ return false;
+ }
+
+ for (Host host : hosts) {
+ if (host == null || host.getStorageUrl() == null || host.getStorageUrl().trim().length() == 0 || !host.getStorageUrl().startsWith("iqn")) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private long[] getNewVolumeIds(long[] volumeIds, long volumeIdToAddOrRemove, boolean add) {
+ if (add) {
+ return getNewVolumeIdsAdd(volumeIds, volumeIdToAddOrRemove);
+ }
+
+ return getNewVolumeIdsRemove(volumeIds, volumeIdToAddOrRemove);
+ }
+
+ private long[] getNewVolumeIdsAdd(long[] volumeIds, long volumeIdToAdd) {
+ List<Long> lstVolumeIds = new ArrayList<Long>();
+
+ if (volumeIds != null) {
+ for (long volumeId : volumeIds) {
+ lstVolumeIds.add(volumeId);
+ }
+ }
+
+ if (lstVolumeIds.contains(volumeIdToAdd)) {
+ return volumeIds;
+ }
+
+ lstVolumeIds.add(volumeIdToAdd);
+
+ return convertArray(lstVolumeIds);
+ }
+
+ private long[] getNewVolumeIdsRemove(long[] volumeIds, long volumeIdToRemove) {
+ List<Long> lstVolumeIds = new ArrayList<Long>();
+
+ if (volumeIds != null) {
+ for (long volumeId : volumeIds) {
+ lstVolumeIds.add(volumeId);
+ }
+ }
+
+ lstVolumeIds.remove(volumeIdToRemove);
+
+ return convertArray(lstVolumeIds);
+ }
+
+ private long[] convertArray(List<Long> items) {
+ if (items == null) {
+ return new long[0];
+ }
+
+ long[] outArray = new long[items.size()];
+
+ for (int i = 0; i < items.size(); i++) {
+ Long value = items.get(i);
+
+ outArray[i] = value;
+ }
+
+ return outArray;
+ }
+
+ private String getVagKey(long storagePoolId) {
+ return "sfVolumeAccessGroup_" + storagePoolId;
+ }
+
+ private String[] getIqnsFromHosts(List<? extends Host> hosts) {
+ if (hosts == null || hosts.size() == 0) {
+ throw new CloudRuntimeException("There do not appear to be any hosts in this cluster.");
+ }
+
+ List<String> lstIqns = new ArrayList<String>();
+
+ for (Host host : hosts) {
+ lstIqns.add(host.getStorageUrl());
+ }
+
+ return lstIqns.toArray(new String[0]);
+ }
+
private long getDefaultMinIops(long storagePoolId) {
StoragePoolDetailVO storagePoolDetail = _storagePoolDetailsDao.findDetail(storagePoolId, SolidFireUtil.CLUSTER_DEFAULT_MIN_IOPS);
@@ -449,6 +635,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
callback.complete(result);
}
+ /*
private void deleteSolidFireAccount(long sfAccountId, SolidFireConnection sfConnection) {
String mVip = sfConnection.getManagementVip();
int mPort = sfConnection.getManagementPort();
@@ -488,6 +675,7 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
return false;
}
+ */
@Override
public void deleteAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback<CommandResult> callback) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
index 3c96c09..8d023d6 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/util/SolidFireUtil.java
@@ -95,32 +95,8 @@ public class SolidFireUtil {
return volumeCreateResult.result.volumeID;
}
- public static SolidFireVolume deleteSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId)
+ public static SolidFireVolume getSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId)
{
- SolidFireVolume sfVolume = getSolidFireVolume(strSfMvip, iSfPort, strSfAdmin, strSfPassword, lVolumeId);
-
- final Gson gson = new GsonBuilder().create();
-
- VolumeToDelete volumeToDelete = new VolumeToDelete(lVolumeId);
-
- String strVolumeToDeleteJson = gson.toJson(volumeToDelete);
-
- executeJsonRpc(strVolumeToDeleteJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
-
- return sfVolume;
- }
-
- public static void purgeSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId) {
- final Gson gson = new GsonBuilder().create();
-
- VolumeToPurge volumeToPurge = new VolumeToPurge(lVolumeId);
-
- String strVolumeToPurgeJson = gson.toJson(volumeToPurge);
-
- executeJsonRpc(strVolumeToPurgeJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
- }
-
- public static SolidFireVolume getSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId) {
final Gson gson = new GsonBuilder().create();
VolumeToGet volumeToGet = new VolumeToGet(lVolumeId);
@@ -164,6 +140,56 @@ public class SolidFireUtil {
return sfVolumes;
}
+ public static List<SolidFireVolume> getDeletedVolumes(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword)
+ {
+ final Gson gson = new GsonBuilder().create();
+
+ ListDeletedVolumes listDeletedVolumes = new ListDeletedVolumes();
+
+ String strListDeletedVolumesJson = gson.toJson(listDeletedVolumes);
+
+ String strListDeletedVolumesResultJson = executeJsonRpc(strListDeletedVolumesJson, strSfMvip, iSfPort,
+ strSfAdmin, strSfPassword);
+
+ VolumeGetResult volumeGetResult = gson.fromJson(strListDeletedVolumesResultJson, VolumeGetResult.class);
+
+ verifyResult(volumeGetResult.result, strListDeletedVolumesResultJson, gson);
+
+ List<SolidFireVolume> deletedVolumes = new ArrayList<SolidFireVolume> ();
+
+ for (VolumeGetResult.Result.Volume volume : volumeGetResult.result.volumes) {
+ deletedVolumes.add(new SolidFireVolume(volume.volumeID, volume.name, volume.iqn, volume.accountID, volume.status, volume.totalSize));
+ }
+
+ return deletedVolumes;
+ }
+
+ public static SolidFireVolume deleteSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId)
+ {
+ SolidFireVolume sfVolume = getSolidFireVolume(strSfMvip, iSfPort, strSfAdmin, strSfPassword, lVolumeId);
+
+ final Gson gson = new GsonBuilder().create();
+
+ VolumeToDelete volumeToDelete = new VolumeToDelete(lVolumeId);
+
+ String strVolumeToDeleteJson = gson.toJson(volumeToDelete);
+
+ executeJsonRpc(strVolumeToDeleteJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
+
+ return sfVolume;
+ }
+
+ public static void purgeSolidFireVolume(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVolumeId)
+ {
+ final Gson gson = new GsonBuilder().create();
+
+ VolumeToPurge volumeToPurge = new VolumeToPurge(lVolumeId);
+
+ String strVolumeToPurgeJson = gson.toJson(volumeToPurge);
+
+ executeJsonRpc(strVolumeToPurgeJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
+ }
+
private static final String ACTIVE = "active";
public static class SolidFireVolume {
@@ -257,17 +283,9 @@ public class SolidFireUtil {
return accountAddResult.result.accountID;
}
- public static void deleteSolidFireAccount(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lAccountId) {
- final Gson gson = new GsonBuilder().create();
-
- AccountToRemove accountToRemove = new AccountToRemove(lAccountId);
-
- String strAccountToRemoveJson = gson.toJson(accountToRemove);
-
- executeJsonRpc(strAccountToRemoveJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
- }
-
- public static SolidFireAccount getSolidFireAccountById(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lSfAccountId) {
+ public static SolidFireAccount getSolidFireAccountById(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword,
+ long lSfAccountId)
+ {
final Gson gson = new GsonBuilder().create();
AccountToGetById accountToGetById = new AccountToGetById(lSfAccountId);
@@ -307,7 +325,20 @@ public class SolidFireUtil {
return new SolidFireAccount(lSfAccountId, strSfAccountName, strSfAccountInitiatorSecret, strSfAccountTargetSecret);
}
- public static class SolidFireAccount {
+ public static void deleteSolidFireAccount(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword,
+ long lAccountId)
+ {
+ final Gson gson = new GsonBuilder().create();
+
+ AccountToRemove accountToRemove = new AccountToRemove(lAccountId);
+
+ String strAccountToRemoveJson = gson.toJson(accountToRemove);
+
+ executeJsonRpc(strAccountToRemoveJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
+ }
+
+ public static class SolidFireAccount
+ {
private final long _id;
private final String _name;
private final String _initiatorSecret;
@@ -358,7 +389,9 @@ public class SolidFireUtil {
SolidFireAccount sfa = (SolidFireAccount)obj;
- if (_id == sfa._id && _name.equals(sfa._name) && _initiatorSecret.equals(sfa._initiatorSecret) && _targetSecret.equals(sfa._targetSecret)) {
+ if (_id == sfa._id && _name.equals(sfa._name) &&
+ _initiatorSecret.equals(sfa._initiatorSecret) &&
+ _targetSecret.equals(sfa._targetSecret)) {
return true;
}
@@ -366,42 +399,54 @@ public class SolidFireUtil {
}
}
- public static List<SolidFireVolume> getDeletedVolumes(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword) {
+ public static long createSolidFireVag(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, String strVagName,
+ String[] iqns, long[] volumeIds)
+ {
final Gson gson = new GsonBuilder().create();
- ListDeletedVolumes listDeletedVolumes = new ListDeletedVolumes();
+ VagToCreate vagToCreate = new VagToCreate(strVagName, iqns, volumeIds);
- String strListDeletedVolumesJson = gson.toJson(listDeletedVolumes);
+ String strVagCreateJson = gson.toJson(vagToCreate);
- String strListDeletedVolumesResultJson = executeJsonRpc(strListDeletedVolumesJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
+ String strVagCreateResultJson = executeJsonRpc(strVagCreateJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
- VolumeGetResult volumeGetResult = gson.fromJson(strListDeletedVolumesResultJson, VolumeGetResult.class);
+ VagCreateResult vagCreateResult = gson.fromJson(strVagCreateResultJson, VagCreateResult.class);
- verifyResult(volumeGetResult.result, strListDeletedVolumesResultJson, gson);
+ verifyResult(vagCreateResult.result, strVagCreateResultJson, gson);
+
+ return vagCreateResult.result.volumeAccessGroupID;
+ }
- List<SolidFireVolume> deletedVolumes = new ArrayList<SolidFireVolume>();
+ public static void modifySolidFireVag(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVagId,
+ String[] iqns, long[] volumeIds)
+ {
+ final Gson gson = new GsonBuilder().create();
- for (VolumeGetResult.Result.Volume volume : volumeGetResult.result.volumes) {
- deletedVolumes.add(new SolidFireVolume(volume.volumeID, volume.name, volume.iqn, volume.accountID, volume.status, volume.totalSize));
- }
+ VagToModify vagToModify = new VagToModify(lVagId, iqns, volumeIds);
- return deletedVolumes;
+ String strVagModifyJson = gson.toJson(vagToModify);
+
+ executeJsonRpc(strVagModifyJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
}
- public static long createSolidFireVag(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, String strVagName) {
+ public static SolidFireVag getSolidFireVag(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVagId)
+ {
final Gson gson = new GsonBuilder().create();
- VagToCreate vagToCreate = new VagToCreate(strVagName);
+ VagToGet vagToGet = new VagToGet(lVagId);
- String strVagCreateJson = gson.toJson(vagToCreate);
+ String strVagToGetJson = gson.toJson(vagToGet);
- String strVagCreateResultJson = executeJsonRpc(strVagCreateJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
+ String strVagGetResultJson = executeJsonRpc(strVagToGetJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
- VagCreateResult vagCreateResult = gson.fromJson(strVagCreateResultJson, VagCreateResult.class);
+ VagGetResult vagGetResult = gson.fromJson(strVagGetResultJson, VagGetResult.class);
- verifyResult(vagCreateResult.result, strVagCreateResultJson, gson);
+ verifyResult(vagGetResult.result, strVagGetResultJson, gson);
- return vagCreateResult.result.volumeAccessGroupID;
+ String[] vagIqns = getVagIqns(vagGetResult, lVagId);
+ long[] vagVolumeIds = getVagVolumeIds(vagGetResult, lVagId);
+
+ return new SolidFireVag(lVagId, vagIqns, vagVolumeIds);
}
public static void deleteSolidFireVag(String strSfMvip, int iSfPort, String strSfAdmin, String strSfPassword, long lVagId) {
@@ -414,6 +459,64 @@ public class SolidFireUtil {
executeJsonRpc(strVagToDeleteJson, strSfMvip, iSfPort, strSfAdmin, strSfPassword);
}
+ public static class SolidFireVag
+ {
+ private final long _id;
+ private final String[] _initiators;
+ private final long[] _volumeIds;
+
+ public SolidFireVag(long id, String[] initiators, long[] volumeIds)
+ {
+ _id = id;
+ _initiators = initiators;
+ _volumeIds = volumeIds;
+ }
+
+ public long getId()
+ {
+ return _id;
+ }
+
+ public String[] getInitiators()
+ {
+ return _initiators;
+ }
+
+ public long[] getVolumeIds()
+ {
+ return _volumeIds;
+ }
+
+ @Override
+ public int hashCode() {
+ return String.valueOf(_id).hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(_id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ if (!obj.getClass().equals(SolidFireVag.class)) {
+ return false;
+ }
+
+ SolidFireVag sfvag = (SolidFireVag)obj;
+
+ if (_id == sfvag._id) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
@SuppressWarnings("unused")
private static final class VolumeToCreate {
private final String method = "CreateVolume";
@@ -466,7 +569,59 @@ public class SolidFireUtil {
}
@SuppressWarnings("unused")
- private static final class VolumeToDelete {
+ private static final class VolumeToGet
+ {
+ private final String method = "ListActiveVolumes";
+ private final VolumeToGetParams params;
+
+ private VolumeToGet(final long lVolumeId)
+ {
+ params = new VolumeToGetParams(lVolumeId);
+ }
+
+ private static final class VolumeToGetParams
+ {
+ private final long startVolumeID;
+ private final long limit = 1;
+
+ private VolumeToGetParams(final long lVolumeId)
+ {
+ startVolumeID = lVolumeId;
+ }
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static final class VolumesToGetForAccount
+ {
+ private final String method = "ListVolumesForAccount";
+ private final VolumesToGetForAccountParams params;
+
+ private VolumesToGetForAccount(final long lAccountId)
+ {
+ params = new VolumesToGetForAccountParams(lAccountId);
+ }
+
+ private static final class VolumesToGetForAccountParams
+ {
+ private final long accountID;
+
+ private VolumesToGetForAccountParams(final long lAccountId)
+ {
+ accountID = lAccountId;
+ }
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static final class ListDeletedVolumes
+ {
+ private final String method = "ListDeletedVolumes";
+ }
+
+ @SuppressWarnings("unused")
+ private static final class VolumeToDelete
+ {
private final String method = "DeleteVolume";
private final VolumeToDeleteParams params;
@@ -484,12 +639,8 @@ public class SolidFireUtil {
}
@SuppressWarnings("unused")
- private static final class ListDeletedVolumes {
- private final String method = "ListDeletedVolumes";
- }
-
- @SuppressWarnings("unused")
- private static final class VolumeToPurge {
+ private static final class VolumeToPurge
+ {
private final String method = "PurgeDeletedVolume";
private final VolumeToPurgeParams params;
@@ -507,56 +658,67 @@ public class SolidFireUtil {
}
@SuppressWarnings("unused")
- private static final class VolumeToGet {
- private final String method = "ListActiveVolumes";
- private final VolumeToGetParams params;
+ private static final class AccountToAdd
+ {
+ private final String method = "AddAccount";
+ private final AccountToAddParams params;
- private VolumeToGet(final long lVolumeId) {
- params = new VolumeToGetParams(lVolumeId);
+ private AccountToAdd(final String strAccountName)
+ {
+ params = new AccountToAddParams(strAccountName);
}
- private static final class VolumeToGetParams {
- private final long startVolumeID;
- private final long limit = 1;
+ private static final class AccountToAddParams
+ {
+ private final String username;
- private VolumeToGetParams(final long lVolumeId) {
- startVolumeID = lVolumeId;
+ private AccountToAddParams(final String strAccountName)
+ {
+ username = strAccountName;
}
}
}
@SuppressWarnings("unused")
- private static final class VolumesToGetForAccount {
- private final String method = "ListVolumesForAccount";
- private final VolumesToGetForAccountParams params;
+ private static final class AccountToGetById
+ {
+ private final String method = "GetAccountByID";
+ private final AccountToGetByIdParams params;
- private VolumesToGetForAccount(final long lAccountId) {
- params = new VolumesToGetForAccountParams(lAccountId);
+ private AccountToGetById(final long lAccountId)
+ {
+ params = new AccountToGetByIdParams(lAccountId);
}
- private static final class VolumesToGetForAccountParams {
+ private static final class AccountToGetByIdParams
+ {
private final long accountID;
- private VolumesToGetForAccountParams(final long lAccountId) {
+ private AccountToGetByIdParams(final long lAccountId)
+ {
accountID = lAccountId;
}
}
}
@SuppressWarnings("unused")
- private static final class AccountToAdd {
- private final String method = "AddAccount";
- private final AccountToAddParams params;
+ private static final class AccountToGetByName
+ {
+ private final String method = "GetAccountByName";
+ private final AccountToGetByNameParams params;
- private AccountToAdd(final String strAccountName) {
- params = new AccountToAddParams(strAccountName);
+ private AccountToGetByName(final String strUsername)
+ {
+ params = new AccountToGetByNameParams(strUsername);
}
- private static final class AccountToAddParams {
+ private static final class AccountToGetByNameParams
+ {
private final String username;
- private AccountToAddParams(final String strAccountName) {
- username = strAccountName;
+ private AccountToGetByNameParams(final String strUsername)
+ {
+ username = strUsername;
}
}
}
@@ -580,55 +742,76 @@ public class SolidFireUtil {
}
@SuppressWarnings("unused")
- private static final class AccountToGetById {
- private final String method = "GetAccountByID";
- private final AccountToGetByIdParams params;
+ private static final class VagToCreate
+ {
+ private final String method = "CreateVolumeAccessGroup";
+ private final VagToCreateParams params;
- private AccountToGetById(final long lAccountId) {
- params = new AccountToGetByIdParams(lAccountId);
+ private VagToCreate(final String strVagName, final String[] iqns, final long[] volumeIds)
+ {
+ params = new VagToCreateParams(strVagName, iqns, volumeIds);
}
- private static final class AccountToGetByIdParams {
- private final long accountID;
+ private static final class VagToCreateParams
+ {
+ private final String name;
+ private final String[] initiators;
+ private final long[] volumes;
- private AccountToGetByIdParams(final long lAccountId) {
- accountID = lAccountId;
+ private VagToCreateParams(final String strVagName, final String[] iqns, final long[] volumeIds)
+ {
+ name = strVagName;
+ initiators = iqns;
+ volumes = volumeIds;
}
}
}
@SuppressWarnings("unused")
- private static final class AccountToGetByName {
- private final String method = "GetAccountByName";
- private final AccountToGetByNameParams params;
+ private static final class VagToModify
+ {
+ private final String method = "ModifyVolumeAccessGroup";
+ private final VagToModifyParams params;
- private AccountToGetByName(final String strUsername) {
- params = new AccountToGetByNameParams(strUsername);
+ private VagToModify(final long lVagName, final String[] iqns, final long[] volumeIds)
+ {
+ params = new VagToModifyParams(lVagName, iqns, volumeIds);
}
- private static final class AccountToGetByNameParams {
- private final String username;
-
- private AccountToGetByNameParams(final String strUsername) {
- username = strUsername;
+ private static final class VagToModifyParams
+ {
+ private final long volumeAccessGroupID;
+ private final String[] initiators;
+ private final long[] volumes;
+
+ private VagToModifyParams(final long lVagName, final String[] iqns, final long[] volumeIds)
+ {
+ volumeAccessGroupID = lVagName;
+ initiators = iqns;
+ volumes = volumeIds;
}
}
}
@SuppressWarnings("unused")
- private static final class VagToCreate {
- private final String method = "CreateVolumeAccessGroup";
- private final VagToCreateParams params;
+ private static final class VagToGet
+ {
+ private final String method = "ListVolumeAccessGroups";
+ private final VagToGetParams params;
- private VagToCreate(final String strVagName) {
- params = new VagToCreateParams(strVagName);
+ private VagToGet(final long lVagId)
+ {
+ params = new VagToGetParams(lVagId);
}
- private static final class VagToCreateParams {
- private final String name;
+ private static final class VagToGetParams
+ {
+ private final long startVolumeAccessGroupID;
+ private final long limit = 1;
- private VagToCreateParams(final String strVagName) {
- name = strVagName;
+ private VagToGetParams(final long lVagId)
+ {
+ startVolumeAccessGroupID = lVagId;
}
}
}
@@ -707,7 +890,25 @@ public class SolidFireUtil {
}
}
- private static final class JsonError {
+ private static final class VagGetResult
+ {
+ private Result result;
+
+ private static final class Result
+ {
+ private Vag[] volumeAccessGroups;
+
+ private static final class Vag
+ {
+ private long volumeAccessGroupID;
+ private String[] initiators;
+ private long[] volumes;
+ }
+ }
+ }
+
+ private static final class JsonError
+ {
private Error error;
private static final class Error {
@@ -762,7 +963,7 @@ public class SolidFireUtil {
httpClient = getHttpClient(iPort);
- URI uri = new URI("https://" + strMvip + ":" + iPort + "/json-rpc/1.0");
+ URI uri = new URI("https://" + strMvip + ":" + iPort + "/json-rpc/5.0");
AuthScope authScope = new AuthScope(uri.getHost(), uri.getPort(), AuthScope.ANY_SCHEME);
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(strAdmin, strPassword);
@@ -865,4 +1066,26 @@ public class SolidFireUtil {
throw new CloudRuntimeException("Could not determine the total size of the volume for volume ID of " + lVolumeId + ".");
}
+
+ private static String[] getVagIqns(VagGetResult vagGetResult, long lVagId)
+ {
+ if (vagGetResult.result.volumeAccessGroups != null && vagGetResult.result.volumeAccessGroups.length == 1 &&
+ vagGetResult.result.volumeAccessGroups[0].volumeAccessGroupID == lVagId)
+ {
+ return vagGetResult.result.volumeAccessGroups[0].initiators;
+ }
+
+ throw new CloudRuntimeException("Could not determine the IQNs of the volume access group for volume access group ID of " + lVagId + ".");
+ }
+
+ private static long[] getVagVolumeIds(VagGetResult vagGetResult, long lVagId)
+ {
+ if (vagGetResult.result.volumeAccessGroups != null && vagGetResult.result.volumeAccessGroups.length == 1 &&
+ vagGetResult.result.volumeAccessGroups[0].volumeAccessGroupID == lVagId)
+ {
+ return vagGetResult.result.volumeAccessGroups[0].volumes;
+ }
+
+ throw new CloudRuntimeException("Could not determine the volume IDs of the volume access group for volume access group ID of " + lVagId + ".");
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 5f15cac..ac0c438 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -1434,8 +1434,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
Volume volume = _volumeDao.findById(volumeId);
VMInstanceVO vm = _vmInstanceDao.findById(vmId);
- String errorMsg = "Failed to detach volume: " + volume.getName() + " from VM: " + vm.getHostName();
- boolean sendCommand = (vm.getState() == State.Running);
+ String errorMsg = "Failed to detach volume " + volume.getName() + " from VM " + vm.getHostName();
+ boolean sendCommand = vm.getState() == State.Running;
Long hostId = vm.getHostId();
@@ -1449,10 +1449,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
}
+ HostVO host = null;
StoragePoolVO volumePool = _storagePoolDao.findById(volume.getPoolId());
if (hostId != null) {
- HostVO host = _hostDao.findById(hostId);
+ host = _hostDao.findById(hostId);
if (host != null && host.getHypervisorType() == HypervisorType.XenServer && volumePool.isManaged()) {
sendCommand = true;
@@ -1481,10 +1482,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
}
+ DataStore dataStore = dataStoreMgr.getDataStore(volume.getPoolId(), DataStoreRole.Primary);
+
if (!sendCommand || (answer != null && answer.getResult())) {
// Mark the volume as detached
_volsDao.detachVolume(volume.getId());
+ volService.disconnectVolumeFromHost(volFactory.getVolume(volume.getId()), host, dataStore);
+
return _volsDao.findById(volumeId);
} else {
@@ -1924,13 +1929,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
private VolumeVO sendAttachVolumeCommand(UserVmVO vm, VolumeVO volumeToAttach, Long deviceId) {
- String errorMsg = "Failed to attach volume: " + volumeToAttach.getName() + " to VM: " + vm.getHostName();
- boolean sendCommand = (vm.getState() == State.Running);
+ String errorMsg = "Failed to attach volume " + volumeToAttach.getName() + " to VM " + vm.getHostName();
+ boolean sendCommand = vm.getState() == State.Running;
AttachAnswer answer = null;
Long hostId = vm.getHostId();
if (hostId == null) {
hostId = vm.getLastHostId();
+
HostVO host = _hostDao.findById(hostId);
if (host != null && host.getHypervisorType() == HypervisorType.VMware) {
@@ -1949,6 +1955,22 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
}
+ DataStore dataStore = dataStoreMgr.getDataStore(volumeToAttachStoragePool.getId(), DataStoreRole.Primary);
+
+ boolean queryForChap = true;
+
+ if (host != null) {
+ try {
+ // if connectVolumeToHost returns true, then we do not want to use CHAP because the volume is already connected to the host(s)
+ queryForChap = !volService.connectVolumeToHost(volFactory.getVolume(volumeToAttach.getId()), host, dataStore);
+ }
+ catch (Exception e) {
+ volService.disconnectVolumeFromHost(volFactory.getVolume(volumeToAttach.getId()), host, dataStore);
+
+ throw new CloudRuntimeException(e.getMessage());
+ }
+ }
+
if (sendCommand) {
if (host.getHypervisorType() == HypervisorType.KVM &&
volumeToAttachStoragePool.isManaged() &&
@@ -1963,9 +1985,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
AttachCommand cmd = new AttachCommand(disk, vm.getInstanceName());
- VolumeInfo volumeInfo = volFactory.getVolume(volumeToAttach.getId());
- DataStore dataStore = dataStoreMgr.getDataStore(volumeToAttachStoragePool.getId(), DataStoreRole.Primary);
- ChapInfo chapInfo = volService.getChapInfo(volumeInfo, dataStore);
+ ChapInfo chapInfo = queryForChap ? volService.getChapInfo(volFactory.getVolume(volumeToAttach.getId()), dataStore) : null;
Map<String, String> details = new HashMap<String, String>();
@@ -1987,6 +2007,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
try {
answer = (AttachAnswer)_agentMgr.send(hostId, cmd);
} catch (Exception e) {
+ volService.disconnectVolumeFromHost(volFactory.getVolume(volumeToAttach.getId()), host, dataStore);
+
throw new CloudRuntimeException(errorMsg + " due to: " + e.getMessage());
}
}
@@ -2023,6 +2045,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
errorMsg += "; " + details;
}
}
+
+ volService.disconnectVolumeFromHost(volFactory.getVolume(volumeToAttach.getId()), host, dataStore);
+
throw new CloudRuntimeException(errorMsg);
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ae35782c/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
index 1b2a102..b306b0c 100755
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
@@ -698,7 +698,9 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
ManagedObjectReference morDs = oc.getObj();
String name = (String)VmwareHelper.getPropValue(oc, "name");
- dsList.add(new Pair<ManagedObjectReference, String>(morDs, name));
+ if (!name.startsWith("-iqn.")) {
+ dsList.add(new Pair<ManagedObjectReference, String>(morDs, name));
+ }
}
}
}