mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-6170 (VMware root-disk support for managed storage)
This commit is contained in:
parent
d68e13fcbd
commit
0879ab812e
|
|
@ -29,10 +29,16 @@ import javax.inject.Inject;
|
|||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
|
|
@ -48,6 +54,7 @@ import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
|
|||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.cluster.ClusterManager;
|
||||
|
|
@ -76,7 +83,10 @@ import com.cloud.secstorage.CommandExecLogVO;
|
|||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
|
||||
import com.cloud.utils.Pair;
|
||||
|
|
@ -123,6 +133,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
|
|||
private VMInstanceDao _vmDao;
|
||||
@Inject
|
||||
private ClusterManager _clusterMgr;
|
||||
@Inject
|
||||
VolumeDao _volumeDao;
|
||||
@Inject
|
||||
PrimaryDataStoreDao _storagePoolDao;
|
||||
@Inject
|
||||
VolumeDataFactory _volFactory;
|
||||
|
||||
protected VMwareGuru() {
|
||||
super();
|
||||
|
|
@ -476,4 +492,43 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
|
|||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {VmwareReserveCpu, VmwareReserveMemory};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Command> finalizeExpungeVolumes(VirtualMachine vm) {
|
||||
List<Command> commands = new ArrayList<Command>();
|
||||
|
||||
List<VolumeVO> volumes = _volumeDao.findByInstance(vm.getId());
|
||||
|
||||
if (volumes != null) {
|
||||
for (VolumeVO volume : volumes) {
|
||||
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
|
||||
|
||||
// storagePool should be null if we are expunging a volume that was never
|
||||
// attached to a VM that was started (the "trick" for storagePool to be null
|
||||
// is that none of the VMs this volume may have been attached to were ever started,
|
||||
// so the volume was never assigned to a storage pool)
|
||||
if (storagePool != null && storagePool.isManaged() && volume.getVolumeType() == Volume.Type.ROOT) {
|
||||
VolumeInfo volumeInfo = _volFactory.getVolume(volume.getId());
|
||||
PrimaryDataStore primaryDataStore = (PrimaryDataStore)volumeInfo.getDataStore();
|
||||
Map<String, String> details = primaryDataStore.getDetails();
|
||||
|
||||
if (details == null) {
|
||||
details = new HashMap<String, String>();
|
||||
|
||||
primaryDataStore.setDetails(details);
|
||||
}
|
||||
|
||||
details.put(DiskTO.MANAGED, Boolean.TRUE.toString());
|
||||
|
||||
DeleteCommand cmd = new DeleteCommand(volumeInfo.getTO());
|
||||
|
||||
commands.add(cmd);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1412,9 +1412,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
DiskTO[] disks = validateDisks(vmSpec.getDisks());
|
||||
assert (disks.length > 0);
|
||||
NicTO[] nics = vmSpec.getNics();
|
||||
Map<String, String> iqnToPath = new HashMap<String, String>();
|
||||
|
||||
HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails = inferDatastoreDetailsFromDiskInfo(hyperHost, context, disks, iqnToPath, cmd);
|
||||
HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails = inferDatastoreDetailsFromDiskInfo(hyperHost, context, disks, cmd);
|
||||
if ((dataStoresDetails == null) || (dataStoresDetails.isEmpty())) {
|
||||
String msg = "Unable to locate datastore details of the volumes to be attached";
|
||||
s_logger.error(msg);
|
||||
|
|
@ -1471,9 +1470,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
|
||||
for (DiskTO vol : disks) {
|
||||
if (vol.getType() == Volume.Type.ROOT) {
|
||||
DataStoreTO primaryStore = vol.getData().getDataStore();
|
||||
/** @todo Mike T. update this in 4.4 to support root disks on managed storage */
|
||||
rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
|
||||
Map<String, String> details = vol.getDetails();
|
||||
boolean managed = false;
|
||||
|
||||
if (details != null) {
|
||||
managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
|
||||
}
|
||||
|
||||
if (managed) {
|
||||
String datastoreName = VmwareResource.getDatastoreName(details.get(DiskTO.IQN));
|
||||
|
||||
rootDiskDataStoreDetails = dataStoresDetails.get(datastoreName);
|
||||
}
|
||||
else {
|
||||
DataStoreTO primaryStore = vol.getData().getDataStore();
|
||||
|
||||
rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1759,7 +1772,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
|
||||
vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMask));
|
||||
postNvpConfigBeforeStart(vmMo, vmSpec);
|
||||
postDiskConfigBeforeStart(vmMo, vmSpec, sortedDisks, ideControllerKey, scsiControllerKey);
|
||||
|
||||
Map<String, String> iqnToPath = new HashMap<String, String>();
|
||||
|
||||
postDiskConfigBeforeStart(vmMo, vmSpec, sortedDisks, ideControllerKey, scsiControllerKey, iqnToPath);
|
||||
|
||||
//
|
||||
// Power-on VM
|
||||
|
|
@ -1891,7 +1907,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
final String datastoreDiskPath;
|
||||
|
||||
if (isManaged) {
|
||||
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
|
||||
if (volumeTO.getVolumeType() == Volume.Type.ROOT) {
|
||||
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, dsMo.getName());
|
||||
}
|
||||
else {
|
||||
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
|
||||
}
|
||||
} else {
|
||||
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
|
||||
}
|
||||
|
|
@ -2177,9 +2198,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
return controllerKey;
|
||||
}
|
||||
|
||||
private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey, int scsiControllerKey)
|
||||
throws Exception {
|
||||
|
||||
private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey,
|
||||
int scsiControllerKey, Map<String, String> iqnToPath) throws Exception {
|
||||
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
|
||||
|
||||
for (DiskTO vol : sortedDisks) {
|
||||
|
|
@ -2194,14 +2214,45 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
String[] diskChain = diskInfo.getDiskChain();
|
||||
assert (diskChain.length > 0);
|
||||
|
||||
Map<String, String> details = vol.getDetails();
|
||||
boolean managed = false;
|
||||
|
||||
if (details != null) {
|
||||
managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
|
||||
}
|
||||
|
||||
DatastoreFile file = new DatastoreFile(diskChain[0]);
|
||||
if (!file.getFileBaseName().equalsIgnoreCase(volumeTO.getPath())) {
|
||||
if (s_logger.isInfoEnabled())
|
||||
s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + file.getFileBaseName());
|
||||
|
||||
if (managed) {
|
||||
DatastoreFile originalFile = new DatastoreFile(volumeTO.getPath());
|
||||
|
||||
if (!file.getFileBaseName().equalsIgnoreCase(originalFile.getFileBaseName())) {
|
||||
if (s_logger.isInfoEnabled())
|
||||
s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + diskChain[0]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!file.getFileBaseName().equalsIgnoreCase(volumeTO.getPath())) {
|
||||
if (s_logger.isInfoEnabled())
|
||||
s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + file.getFileBaseName());
|
||||
}
|
||||
}
|
||||
|
||||
VolumeObjectTO volInSpec = getVolumeInSpec(vmSpec, volumeTO);
|
||||
volInSpec.setPath(file.getFileBaseName());
|
||||
|
||||
if (managed) {
|
||||
String datastoreVolumePath = diskChain[0];
|
||||
|
||||
iqnToPath.put(details.get(DiskTO.IQN), datastoreVolumePath);
|
||||
|
||||
vol.setPath(datastoreVolumePath);
|
||||
volumeTO.setPath(datastoreVolumePath);
|
||||
volInSpec.setPath(datastoreVolumePath);
|
||||
}
|
||||
else {
|
||||
volInSpec.setPath(file.getFileBaseName());
|
||||
}
|
||||
|
||||
volInSpec.setChainInfo(_gson.toJson(diskInfo));
|
||||
}
|
||||
}
|
||||
|
|
@ -2263,7 +2314,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
}
|
||||
|
||||
private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context,
|
||||
DiskTO[] disks, Map<String, String> iqnToPath, Command cmd) throws Exception {
|
||||
DiskTO[] disks, Command cmd) throws Exception {
|
||||
HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> mapIdToMors = new HashMap<String, Pair<ManagedObjectReference, DatastoreMO>>();
|
||||
|
||||
assert (hyperHost != null) && (context != null);
|
||||
|
|
@ -2299,8 +2350,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDatastore);
|
||||
String datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
|
||||
|
||||
iqnToPath.put(iScsiName, datastoreVolumePath);
|
||||
|
||||
volumeTO.setPath(datastoreVolumePath);
|
||||
vol.setPath(datastoreVolumePath);
|
||||
}
|
||||
|
|
@ -3462,6 +3511,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
}
|
||||
|
||||
addRemoveInternetScsiTargetsToAllHosts(false, lstManagedTargets, lstHosts);
|
||||
|
||||
rescanAllHosts(lstHosts);
|
||||
}
|
||||
|
||||
private void addRemoveInternetScsiTargetsToAllHosts(final boolean add, final List<HostInternetScsiHbaStaticTarget> lstTargets,
|
||||
|
|
@ -4281,7 +4332,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
|||
|
||||
public Answer execute(DeleteCommand cmd) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
|
||||
s_logger.info("Executing resource DeleteCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import org.apache.cloudstack.storage.command.DeleteCommand;
|
|||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
import org.apache.cloudstack.storage.command.ForgetObjectCmd;
|
||||
import org.apache.cloudstack.storage.command.IntroduceObjectCmd;
|
||||
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||
|
|
@ -1420,10 +1421,17 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||
return new CreateObjectAnswer(newSnapshot);
|
||||
}
|
||||
|
||||
// format: [datastore_name] file_name.vmdk (the '[' and ']' chars should only be used to denote the datastore)
|
||||
private String getManagedDatastoreNameFromPath(String path) {
|
||||
int lastIndexOf = path.lastIndexOf("]");
|
||||
|
||||
return path.substring(1, lastIndexOf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer deleteVolume(DeleteCommand cmd) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
|
||||
s_logger.info("Executing resource DeleteCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -1431,8 +1439,23 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
|
||||
VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
|
||||
DataStoreTO store = vol.getDataStore();
|
||||
PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO)store;
|
||||
|
||||
Map<String, String> details = primaryDataStoreTO.getDetails();
|
||||
boolean isManaged = false;
|
||||
String managedDatastoreName = null;
|
||||
|
||||
if (details != null) {
|
||||
isManaged = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED));
|
||||
|
||||
if (isManaged) {
|
||||
managedDatastoreName = getManagedDatastoreNameFromPath(vol.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost,
|
||||
isManaged ? managedDatastoreName : store.getUuid());
|
||||
|
||||
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
|
||||
if (morDs == null) {
|
||||
String msg = "Unable to find datastore based on volume mount point " + store.getUuid();
|
||||
s_logger.error(msg);
|
||||
|
|
|
|||
Loading…
Reference in New Issue