/* * Copyright (c) 2012-2015 iWave Software LLC * All Rights Reserved */ package com.emc.sa.service.aix; import static com.emc.sa.service.vipr.ViPRExecutionUtils.addAffectedResource; import java.util.Collection; import java.util.List; import java.util.Map; import com.emc.aix.AixSystem; import com.emc.aix.model.MountPoint; import com.emc.sa.engine.ExecutionUtils; import com.emc.sa.machinetags.KnownMachineTags; import com.emc.sa.service.aix.UnmountBlockVolumeHelper.VolumeSpec; import com.emc.sa.service.aix.tasks.AddToFilesystemsConfig; import com.emc.sa.service.aix.tasks.AixExecutionTask; import com.emc.sa.service.aix.tasks.CheckForPowerPath; import com.emc.sa.service.aix.tasks.CreateDirectory; import com.emc.sa.service.aix.tasks.DeleteDirectory; import com.emc.sa.service.aix.tasks.FindHDiskForVolume; import com.emc.sa.service.aix.tasks.FindMountPointsForVolumes; import com.emc.sa.service.aix.tasks.FindMultiPathEntriesForMountPoint; import com.emc.sa.service.aix.tasks.FindPowerPathEntriesForMountPoint; import com.emc.sa.service.aix.tasks.GetDirectoryContents; import com.emc.sa.service.aix.tasks.ListMountPoints; import com.emc.sa.service.aix.tasks.MountPath; import com.emc.sa.service.aix.tasks.RemoveFromFilesystemsConfig; import com.emc.sa.service.aix.tasks.RemovePowerPathDevice; import com.emc.sa.service.aix.tasks.RescanDevices; import com.emc.sa.service.aix.tasks.UnmountPath; import com.emc.sa.service.aix.tasks.UpdatePowerPathEntries; import com.emc.sa.service.aix.tasks.VerifyMountPoint; import com.emc.sa.service.vipr.ViPRExecutionUtils; import com.emc.sa.service.vipr.block.tasks.RemoveBlockVolumeMachineTag; import com.emc.sa.service.vipr.block.tasks.SetBlockVolumeMachineTag; import com.emc.storageos.model.block.BlockObjectRestRep; import com.emc.storageos.model.block.VolumeRestRep; import com.iwave.ext.linux.model.PowerPathDevice; public class AixSupport { private final AixSystem targetSystem; public AixSupport(AixSystem targetSystem) { this.targetSystem = targetSystem; } public String getHostName() { return targetSystem.getHost(); } public AixSystem getTargetSystem() { return this.targetSystem; } protected void logDebug(String message, Object... args) { ExecutionUtils.currentContext().logDebug(message, args); } protected void logInfo(String message, Object... args) { ExecutionUtils.currentContext().logInfo(message, args); } protected void logWarn(String message, Object... args) { ExecutionUtils.currentContext().logWarn(message, args); } protected void logError(String message, Object... args) { ExecutionUtils.currentContext().logError(message, args); } protected void logError(Throwable cause, String message, Object... args) { ExecutionUtils.currentContext().logError(message, args); } public void setVolumeMountPointTag(BlockObjectRestRep volume, String mountPoint) { ExecutionUtils.execute(new SetBlockVolumeMachineTag(volume.getId(), getMountPointTagName(), mountPoint)); ExecutionUtils.addRollback(new RemoveBlockVolumeMachineTag(volume.getId(), getMountPointTagName())); addAffectedResource(volume.getId()); } public void removeVolumesMountPointTag(Collection<? extends VolumeRestRep> volumes) { for (VolumeRestRep volume : volumes) { removeVolumeMountPointTag(volume); } } public void removeVolumeMountPointTag(BlockObjectRestRep volume) { ExecutionUtils.execute(new RemoveBlockVolumeMachineTag(volume.getId(), getMountPointTagName())); addAffectedResource(volume.getId()); } public void findPowerPathDevices(List<VolumeSpec> volumes) { execute(new FindPowerPathEntriesForMountPoint(volumes)); } public void findMultipathDevices(List<VolumeSpec> volumes) { execute(new FindMultiPathEntriesForMountPoint(volumes)); } private String getMountPointTagName() { return KnownMachineTags.getHostMountPointTagName(targetSystem.getHostId()); } public void updatePowerPathEntries() { execute(new UpdatePowerPathEntries()); } public void removePowerPathDevices(Collection<PowerPathDevice> devices) { for (PowerPathDevice device : devices) { execute(new RemovePowerPathDevice(device)); } } public void deleteDirectory(String path) { execute(new DeleteDirectory(path)); } public void createDirectory(String path) { execute(new CreateDirectory(path)); addRollback(new DeleteDirectory(path)); } public boolean isDirectoryEmpty(String path) { return execute(new GetDirectoryContents(path)).isEmpty(); } public MountPoint findMountPoint(String path) { return getMountPoints().get(path); } public void verifyMountPoint(String path) { execute(new VerifyMountPoint(path)); } public void findMountPoints(List<VolumeSpec> volumes) { execute(new FindMountPointsForVolumes(targetSystem.getHostId(), volumes)); } public Map<String, MountPoint> getMountPoints() { return execute(new ListMountPoints()); } protected <T> T execute(AixExecutionTask<T> task) { task.setTargetSystem(targetSystem); return ViPRExecutionUtils.execute(task); } public boolean checkForPowerPath() { return execute(new CheckForPowerPath()); } public void mount(String mountPoint) { execute(new MountPath(mountPoint)); addRollback(new UnmountPath(mountPoint)); } public void unmount(String mountPoint) { execute(new UnmountPath(mountPoint)); } public String findHDisk(BlockObjectRestRep volume, boolean usePowerPath) { String rhdiskDevice = execute(new FindHDiskForVolume(volume, usePowerPath)); if (rhdiskDevice == null) { throw new IllegalStateException(String.format( "Could not find hdisk for Volume %s: - PowerPath/MPIO or SAN connectivity may need attention from an administrator. ", volume.getWwn().toLowerCase())); } logInfo("aix.support.found.hdisk", rhdiskDevice, volume.getWwn()); return rhdiskDevice.replaceAll("rhdisk", "hdisk"); } protected <T extends BlockObjectRestRep> void getDeviceFailed(T volume, String errorMessage, IllegalStateException exception) { ExecutionUtils.fail("failTask.getDeviceName", volume.getWwn(), errorMessage, exception.getMessage()); } public void rescanDevices() { execute(new RescanDevices()); } public void addToFilesystemsConfig(String device, String mountPoint, String fsType) { execute(new AddToFilesystemsConfig(device, mountPoint, fsType)); addRollback(new RemoveFromFilesystemsConfig(mountPoint)); } public void removeFromFilesystemsConfig(String mountPoint) { execute(new RemoveFromFilesystemsConfig(mountPoint)); } public String getDevice(BlockObjectRestRep volume, boolean usePowerPath) { try { // we will retry this up to 5 times int remainingAttempts = 5; while (remainingAttempts-- >= 0) { try { return findHDisk(volume, usePowerPath); } catch (IllegalStateException e) { String errorMessage = String.format("Unable to find device for WWN %s. %s more attempts will be made.", volume.getWwn(), remainingAttempts); if (remainingAttempts == 0) { getDeviceFailed(volume, errorMessage, e); } logWarn(errorMessage); Thread.sleep(5000); rescanDevices(); } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return null; } public void addRollback(AixExecutionTask<?> rollbackTask) { rollbackTask.setTargetSystem(targetSystem); ExecutionUtils.addRollback(rollbackTask); } }