/*
* Copyright (c) 2012-2015 iWave Software LLC
* All Rights Reserved
*/
package com.emc.sa.service.windows;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import com.emc.sa.engine.ExecutionUtils;
import com.emc.sa.engine.bind.BindingUtils;
import com.emc.sa.service.ArtificialFailures;
import com.emc.sa.service.vipr.ViPRService;
import com.emc.storageos.model.block.BlockObjectRestRep;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.iwave.ext.windows.WindowsSystemWinRM;
import com.iwave.ext.windows.model.Disk;
import com.iwave.ext.windows.model.Volume;
import com.iwave.ext.windows.model.wmi.DiskDrive;
public class ExtendDriveHelper {
private final WindowsSupport windows;
private Collection<? extends BlockObjectRestRep> volumes;
private Map<? extends BlockObjectRestRep, DiskDrive> volume2disk;
private Map<BlockObjectRestRep, String> volume2mountPoint;
private long volumeSizeInBytes;
private boolean foundClusteredVolume = false;
public static List<ExtendDriveHelper> createHelpers(List<WindowsSystemWinRM> windowsSystems, long volumeSizeInBytes) {
List<ExtendDriveHelper> helpers = Lists.newArrayList();
for (WindowsSystemWinRM windowsSystem : windowsSystems) {
WindowsSupport windowsSupport = new WindowsSupport(windowsSystem);
ExtendDriveHelper extendDriveHelper = new ExtendDriveHelper(windowsSupport, volumeSizeInBytes);
BindingUtils.bind(extendDriveHelper, ExecutionUtils.currentContext().getParameters());
helpers.add(extendDriveHelper);
}
return helpers;
}
private ExtendDriveHelper(WindowsSupport windowsSupport, long volumeSizeInBytes) {
windows = windowsSupport;
this.volumeSizeInBytes = volumeSizeInBytes;
}
public void setVolumes(Collection<BlockObjectRestRep> volumes) {
this.volumes = volumes;
}
public void precheck() {
windows.verifyWinRM();
volume2disk = windows.findDisks(volumes);
// Get the actual mount points for the volumes from the system
volume2mountPoint = Maps.newHashMap();
for (Map.Entry<? extends BlockObjectRestRep, DiskDrive> entry : volume2disk.entrySet()) {
BlockObjectRestRep volume = entry.getKey();
DiskDrive disk = entry.getValue();
logInfo("extendDrive.diskVolumeOnHost", disk.getNumber(), windows.getHostName());
Disk detail = windows.getDiskDetail(disk);
if (windows.isClustered()) {
if (isDiskVolumeOnHost(detail)) { // host in cluster and found
foundClusteredVolume = true;
} else { // host in cluster and not found, don't process
continue;
}
}
windows.checkPartitionRestriction(disk, volumeSizeInBytes);
String mountPoint = getMountPoint(disk, detail);
logInfo("extendDrive.volumeMountPoint", volume.getName(), mountPoint);
volume2mountPoint.put(volume, mountPoint);
}
}
/**
* Helper function to determine if the volumes is on host when shared export to cluster
*
* @return true or false if the volume found on the host
*/
public boolean isDiskVolumeOnHost(Disk detail) {
if (detail == null) {
return false;
}
if ((detail.getVolumes() == null) || (detail.getVolumes().isEmpty())) {
return false;
}
if (detail.getVolumes().size() > 1) {
return false;
}
return true;
}
/**
* Clustered volume only appear on one host. After precheck is done, this can be called to
* see if the volume was found on the host.
*
* @return true or false if the volume was found on the host
*/
public boolean foundClusteredVolume() {
return foundClusteredVolume;
}
/**
* Gets the mount point for the given disk drive. The disk must have only a single volume and that volume must have
* a non-empty mount point.
*
* @param disk
* the disk drive.
* @param detail the detail of the disk
* @return the mount point for the disk.
*/
private String getMountPoint(DiskDrive disk, Disk detail) {
if (detail == null) {
ExecutionUtils.fail("failTask.ExtendDriveHelper.couldNotDetailDisk", disk.getNumber(), disk.getNumber());
}
if ((detail.getVolumes() == null) || (detail.getVolumes().isEmpty())) {
ExecutionUtils.fail("failTask.ExtendDriveHelper.noVolumes", disk.getNumber(), disk.getNumber());
}
if (detail.getVolumes().size() > 1) {
ExecutionUtils.fail("failTask.ExtendDriveHelper.moreThanOneVolume", disk.getNumber(), detail.getVolumes().size());
}
Volume volume = detail.getVolumes().get(0);
String mountPoint = volume.getMountPoint();
if (StringUtils.isBlank(mountPoint)) {
ExecutionUtils
.fail("failTask.ExtendDriveHelper.volumeHasNoMountPoint", disk.getNumber(), volume.getNumber(), volume.getLabel());
}
return mountPoint;
}
public void extendDrives() {
windows.rescanDisks();
for (Map.Entry<? extends BlockObjectRestRep, String> entry : volume2mountPoint.entrySet()) {
BlockObjectRestRep volume = entry.getKey();
String mountPoint = entry.getValue();
ViPRService.artificialFailure(ArtificialFailures.ARTIFICIAL_FAILURE_WINDOWS_BEFORE_EXTEND_DRIVE);
windows.extendDrive(volume, mountPoint);
// Updates the volume mount point, it may have changed
ViPRService.artificialFailure(ArtificialFailures.ARTIFICIAL_FAILURE_WINDOWS_AFTER_EXTEND_DRIVE);
windows.addVolumeMountPoint(volume, mountPoint);
}
ExecutionUtils.clearRollback();
}
private void logInfo(String messageKey, Object... args) {
ExecutionUtils.currentContext().logInfo(ExecutionUtils.getMessage(messageKey, args));
}
}