Changes related to Review Board comments

This commit is contained in:
Mike Tutkowski 2013-07-20 17:44:23 -06:00
parent 6689e83d7f
commit 98dd501a81
1 changed files with 148 additions and 125 deletions

View File

@ -28,6 +28,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.*;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
@ -4073,33 +4074,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return str.replace('/', '-');
}
// This methd can be used to determine if the datastore is active yet.
// When an iSCSI target is created on a host and that target already contains
// the metadata that represents a datastore, the datastore shows up within
// vCenter as existent, but not necessarily active.
// Call this method and pass in the datastore's name to wait, if necessary,
// for the datastore to become active.
private boolean datastoreFileExists(DatastoreMO dsMo, String volumeDatastorePath) {
for (int i = 0; i < 10; i++) {
try {
return dsMo.fileExists(volumeDatastorePath);
}
catch (Exception e) {
if (!e.getMessage().contains("is not accessible")) {
break;
}
}
try {
Thread.sleep(5000);
}
catch (Exception e) {
}
}
return false;
}
@Override
public ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort,
String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception {
@ -4115,7 +4089,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName());
if (!datastoreFileExists(dsMo, volumeDatastorePath)) {
if (!dsMo.fileExists(volumeDatastorePath)) {
String dummyVmName = getWorkerName(context, cmd, 0);
VirtualMachineMO vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
@ -4209,6 +4183,126 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
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 createVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress,
int storagePortNumber, String iqn, String chapName, String chapSecret, String mutualChapName, String mutualChapSecret) throws Exception {
VmwareContext context = getServiceContext();
@ -4242,80 +4336,46 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
lstTargets.add(target);
HostDatastoreSystemMO hostDatastoreSystem = null;
HostStorageSystemMO hostStorageSystem = null;
addRemoveInternetScsiTargetsToAllHosts(true, lstTargets, lstHosts);
final List<Thread> threads = new ArrayList<Thread>();
final List<Exception> exceptions = new ArrayList<Exception>();
rescanAllHosts(lstHosts);
for (Pair<ManagedObjectReference, String> hostPair : lstHosts) {
HostMO host = new HostMO(context, hostPair.first());
hostDatastoreSystem = host.getHostDatastoreSystemMO();
hostStorageSystem = host.getHostStorageSystemMO();
HostMO host = new HostMO(context, lstHosts.get(0).first());
HostDatastoreSystemMO hostDatastoreSystem = host.getHostDatastoreSystemMO();
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;
threads.add(new Thread() {
@Override
public void run() {
try {
hss.addInternetScsiStaticTargets(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.");
}
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
if (exceptions.size() > 0) {
throw new Exception(exceptions.get(0).getMessage());
}
ManagedObjectReference morDs = hostDatastoreSystem.findDatastoreByName(iqn);
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.");
}
return hostDatastoreSystem.createVmfsDatastore(datastoreName, hostScsiDisk);
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
@ -4363,46 +4423,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
lstTargets.add(target);
final List<Thread> threads = new ArrayList<Thread>();
final List<Exception> exceptions = new ArrayList<Exception>();
addRemoveInternetScsiTargetsToAllHosts(false, lstTargets, lstHosts);
for (Pair<ManagedObjectReference, String> hostPair : lstHosts) {
final HostMO host = new HostMO(context, hostPair.first());
final HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO();
for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) {
if (hba instanceof HostInternetScsiHba) {
final String iScsiHbaDevice = hba.getDevice();
Thread thread = new Thread() {
@Override
public void run() {
try {
hostStorageSystem.removeInternetScsiStaticTargets(iScsiHbaDevice, lstTargets);
hostStorageSystem.rescanHba(iScsiHbaDevice);
hostStorageSystem.rescanVmfs();
}
catch (Exception ex) {
exceptions.add(ex);
}
}
};
threads.add(thread);
thread.start();
}
}
}
for (Thread thread : threads) {
thread.join();
}
if (exceptions.size() > 0) {
throw new Exception(exceptions.get(0).getMessage());
}
rescanAllHosts(lstHosts);
}
protected Answer execute(AttachIsoCommand cmd) {