/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.computesystemcontroller.impl.adapter;
import java.net.URI;
import java.util.Collection;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.emc.aix.AixVioCLI;
import com.emc.aix.model.AixVersion;
import com.emc.storageos.computesystemcontroller.exceptions.ComputeSystemControllerException;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.DiscoveredDataObject.CompatibilityStatus;
import com.emc.storageos.db.client.model.Host;
import com.emc.storageos.db.client.model.Host.HostType;
import com.emc.storageos.db.client.model.HostInterface.Protocol;
import com.emc.storageos.db.client.model.Initiator;
import com.emc.storageos.db.client.model.IpInterface;
import com.emc.storageos.db.client.util.CommonTransformerFunctions;
import com.emc.storageos.exceptions.DeviceControllerException;
import com.emc.storageos.util.SanUtils;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.iwave.ext.command.CommandException;
import com.iwave.ext.linux.model.HBAInfo;
@Component
public class AixVioDiscoveryAdapter extends AbstractHostDiscoveryAdapter {
private static final Logger LOG = LoggerFactory.getLogger(AixVioDiscoveryAdapter.class);
private static final String ENT0 = "ent0";
@Override
protected String getSupportedType() {
return HostType.AIXVIO.name();
}
@Override
protected void discoverHost(Host host, HostStateChange changes) {
validateHost(host);
AixVersion version = getVersion(host);
host.setOsVersion(version.toString());
if (getVersionValidator().isValidAixVioVersion(version)) {
host.setCompatibilityStatus(CompatibilityStatus.COMPATIBLE.name());
save(host);
super.discoverHost(host, changes);
}
else {
host.setCompatibilityStatus(CompatibilityStatus.INCOMPATIBLE.name());
save(host);
throw ComputeSystemControllerException.exceptions.incompatibleHostVersion(
getSupportedType(), version.toString(),
getVersionValidator().getAixVioMinimumVersion(false).toString());
}
}
protected void validateHost(Host host) {
getCli(host).executeCommand("pwd");
}
private AixVioCLI getCli(Host vio) {
return new AixVioCLI(vio.getHostName(), vio.getPortNumber(), vio.getUsername(), vio.getPassword());
}
public AixVersion getVersion(Host vio) {
return getCli(vio).getVersion();
}
public void setDbCLient(DbClient dbClient) {
super.setDbClient(dbClient);
}
@Override
protected void discoverIpInterfaces(Host host,
List<IpInterface> oldIpInterfaces) {
// Unable to discover IP interfaces on AIX VIO
}
private void discoverFCInitiator(Host host, Initiator initiator, HBAInfo hba) {
setInitiator(initiator, host);
initiator.setProtocol(Protocol.FC.name());
initiator.setInitiatorNode(SanUtils.normalizeWWN(hba.getWwnn()));
initiator.setInitiatorPort(SanUtils.normalizeWWN(hba.getWwpn()));
setHostInterfaceRegistrationStatus(initiator, host);
save(initiator);
}
private void discoverISCSIInitiator(Host host, Initiator initiator, String iqn) {
setInitiator(initiator, host);
initiator.setInitiatorNode("");
initiator.setInitiatorPort(iqn);
initiator.setProtocol(Protocol.iSCSI.name());
setHostInterfaceRegistrationStatus(initiator, host);
save(initiator);
}
@Override
protected void discoverInitiators(Host host, List<Initiator> oldInitiators, HostStateChange changes) {
AixVioCLI cli = getCli(host);
List<Initiator> addedInitiators = Lists.newArrayList();
try {
for (HBAInfo hba : cli.listInitiators()) {
Initiator initiator;
String wwpn = SanUtils.normalizeWWN(hba.getWwpn());
if (findInitiatorByPort(oldInitiators, wwpn) == null) {
initiator = getOrCreateInitiator(host.getId(), oldInitiators, wwpn);
addedInitiators.add(initiator);
} else {
initiator = getOrCreateInitiator(host.getId(), oldInitiators, wwpn);
}
discoverFCInitiator(host, initiator, hba);
}
} catch (DeviceControllerException e) {
throw e;
} catch (Exception e) {
LOG.error("Failed to list FC Ports, skipping");
}
try {
for (String iqn : cli.listIQNs()) {
Initiator initiator;
if (findInitiatorByPort(oldInitiators, iqn) == null) {
initiator = getOrCreateInitiator(host.getId(), oldInitiators, iqn);
addedInitiators.add(initiator);
} else {
initiator = getOrCreateInitiator(host.getId(), oldInitiators, iqn);
}
discoverISCSIInitiator(host, initiator, iqn);
}
} catch (DeviceControllerException e) {
throw e;
} catch (Exception e) {
LOG.error("Failed to list iSCSI Ports, skipping");
}
// update export groups with new initiators if host is in use.
if (!addedInitiators.isEmpty()) {
Collection<URI> addedInitiatorIds = Lists.newArrayList(Collections2.transform(addedInitiators,
CommonTransformerFunctions.fctnDataObjectToID()));
changes.setNewInitiators(addedInitiatorIds);
}
}
@Override
protected void setNativeGuid(Host host) {
AixVioCLI cli = getCli(host);
try {
String macAddress = cli.getNetworkAdapterMacAddress(ENT0);
if (macAddress != null && !host.getNativeGuid().equalsIgnoreCase(macAddress)) {
checkDuplicateHost(host, macAddress);
info("Setting nativeGuid for " + host.getId() + " as " + macAddress);
host.setNativeGuid(macAddress);
save(host);
}
} catch (CommandException ex) {
LOG.warn("Failed to get MAC address of adapter during discovery");
}
}
}