/*
* Copyright (c) 2008-2011 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.model;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.emc.storageos.services.util.StorageDriverManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.constraint.AlternateIdConstraint;
import com.emc.storageos.db.client.model.DiscoveredDataObject.CompatibilityStatus;
import com.emc.storageos.db.client.model.DiscoveredDataObject.DataCollectionJobStatus;
import com.emc.storageos.db.client.model.DiscoveredDataObject.RegistrationStatus;
import com.emc.storageos.db.client.model.DiscoveredDataObject.Type;
import com.emc.storageos.db.client.upgrade.CustomMigrationCallback;
import com.emc.storageos.db.client.upgrade.callbacks.SMISProviderToStorageProviderMigration;
import com.emc.storageos.db.client.util.NullColumnValueGetter;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.emc.storageos.model.valid.EnumType;
import org.springframework.context.ApplicationContext;
/**
* StorageProvider data object
*/
@Cf("StorageProvider")
public class StorageProvider extends DataObject {
/**
* serialVersionUID
*/
private static final long serialVersionUID = -860528426935487712L;
private static final Logger logger = LoggerFactory.getLogger(StorageProvider.class);
private static StorageDriverManager storageDriverManager = null;
static {
// This class can be used in test setups without application context.
// Ex. DB migration test framework.
ApplicationContext context = StorageDriverManager.getApplicationContext();
if (context != null) {
storageDriverManager = (StorageDriverManager)StorageDriverManager.
getApplicationContext().getBean(StorageDriverManager.STORAGE_DRIVER_MANAGER);
} else {
logger.warn("Cannot set storageDriverManager. Application context is null. Assuming not a real deployment.");
}
}
// Unigue native identifier (system level identifier)
private String _nativeId;
private StringSet _storageSystems;
// provider IP address
private String _ipAddress;
// Secondary IP addresses
private StringSet _secondaryIps;
// provider port number (2001/5988/5989)
private Integer _portNumber;
// user name.
private String _userName;
// password.
private String _password;
// flag indicates whether or not to use SSL protocol.
private Boolean _useSSL;
// IPAddress alternateID is already used inStorageDevice,
// hence used provider ID : IPAddress:portNumber as ID
private String _providerID;
// Provider Description.
private String _description;
// Provider manfacturer.
private String _manufacturer;
// Provider version.
private String _versionString;
// ConnectionStatus tells whether provider is connected to Bourne or not.
private String _connectionStatus = ConnectionStatus.NOTCONNECTED.toString();
// Status of a Scan Job
private String _scanStatus;
// Status Message of a Last Scan Job
private String _lastScanStatusMessage;
// Last Scan Time of a Scan Job
private Long _lastScanTime = 0L;
// Next Scan Time of a Scan Job
private Long _nextScanTime = 0L;
private Long _successScanTime = 0L;
private String _registrationStatus = RegistrationStatus.UNREGISTERED.toString();
// used in finding out whether or not the Provider is Compatible
private String _compatibilityStatus = CompatibilityStatus.UNKNOWN.name();
private String _interfaceType;
// list of decommissioned Systems
private StringSet _decommissionedSystems;
/*
* This map will be used to hold any key value pairs required
* to be fetched during provisioning.
*
* Adding this map to store cinder end point information required
* during the provisioning. During the cinder discovery, the end
* point information will be fetched and kept as key value pairs.
*/
private StringMap keys;
/**
* Element manager URL
*/
private String elementManagerURL;
/**
* Secondry URL
*/
private String secondryURL;
/**
* Secondary set of credentials. This is used for example in the
* case of ScaleIO, where there is a password to SSH into the
* MDM box (primary creds) and the secondary creds will be the
* ones required to run the SCLI commands
*/
private String secondaryPassword;
private String secondaryUsername;
@Name("elementManagerURL")
public String getElementManagerURL() {
return elementManagerURL;
}
public void setElementManagerURL(String elementManagerURL) {
this.elementManagerURL = elementManagerURL;
setChanged("elementManagerURL");
}
@Name("secondryURL")
public String getSecondaryURL() {
return secondryURL;
}
public void setSecondaryURL(String secondryURL) {
this.secondryURL = secondryURL;
setChanged("secondryURL");
}
@Name("secondaryUsername")
public String getSecondaryUsername() {
return secondaryUsername;
}
public void setSecondaryUsername(String username) {
this.secondaryUsername = username;
setChanged("secondaryUsername");
}
@Encrypt
@Name("secondaryPassword")
public String getSecondaryPassword() {
return secondaryPassword;
}
public void setSecondaryPassword(String password) {
this.secondaryPassword = password;
setChanged("secondaryPassword");
}
public static enum InterfaceType {
hicommand,
smis,
ddmc,
vplex,
cinder,
ibmxiv,
scaleioapi,
xtremio,
unity,
ceph;
/**
* Gets the supported system types for the given interface type.
*/
public static List<String> getSystemTypesForInterfaceType(InterfaceType interfaceType) {
List<String> systemTypes = new ArrayList<String>();
if (smis.equals(interfaceType)) {
systemTypes.add(Type.vmax.name());
systemTypes.add(Type.vnxblock.name());
} else if (hicommand.equals(interfaceType)) {
systemTypes.add(Type.hds.name());
} else if (vplex.equals(interfaceType)) {
systemTypes.add(Type.vplex.name());
} else if (cinder.equals(interfaceType)) {
systemTypes.add(Type.openstack.name());
} else if (ibmxiv.equals(interfaceType)) {
systemTypes.add(Type.ibmxiv.name());
} else if (ddmc.equals(interfaceType)) {
systemTypes.add(Type.datadomain.name());
} else if (scaleioapi.equals(interfaceType)) {
systemTypes.add(Type.scaleio.name());
} else if (xtremio.equals(interfaceType)) {
systemTypes.add(Type.xtremio.name());
} else if (ceph.equals(interfaceType)) {
systemTypes.add(Type.ceph.name());
} else if (unity.equals(interfaceType)) {
systemTypes.add(Type.unity.name());
} else if (storageDriverManager != null && storageDriverManager.isProvider(interfaceType.toString())) {
Type type = Type.valueOf(interfaceType.toString());
systemTypes.add(type.name());
}
return systemTypes;
}
}
/**
* ConnectionStatus enum.
*/
public static enum ConnectionStatus {
CONNECTED,
NOTCONNECTED,
INITIALIZING
}
/*********************************************************
* AlternateIDIndex - ProviderID (IPAddress-portNumber) *
* RelationIndex - Empty *
*********************************************************/
@CustomMigrationCallback(callback = SMISProviderToStorageProviderMigration.class)
@Name("ipAddress")
public String getIPAddress() {
return _ipAddress;
}
public void setIPAddress(String ipAddress) {
_ipAddress = ipAddress;
if (null != _portNumber) {
setProviderID(_ipAddress + "-" + _portNumber);
}
setChanged("ipAddress");
}
@Name("secondaryIps")
public StringSet getSecondaryIps() {
if (_secondaryIps == null) {
return new StringSet();
}
return _secondaryIps;
}
public void setSecondaryIps(StringSet secondaryIps) {
_secondaryIps = secondaryIps;
setChanged("secondaryIps");
}
@Name("portNumber")
public Integer getPortNumber() {
return _portNumber;
}
public void setPortNumber(Integer portNumber) {
_portNumber = portNumber;
if (null != _ipAddress) {
setProviderID(_ipAddress + "-" + _portNumber);
}
setChanged("portNumber");
}
@Name("userName")
public String getUserName() {
return _userName;
}
public void setUserName(String userName) {
_userName = userName;
setChanged("userName");
}
@Encrypt
@Name("password")
public String getPassword() {
return _password;
}
public void setPassword(String password) {
_password = password;
setChanged("password");
}
@Name("useSSL")
public Boolean getUseSSL() {
return (_useSSL != null) && _useSSL;
}
public void setUseSSL(Boolean useSSL) {
_useSSL = useSSL;
setChanged("useSSL");
}
public void setStorageSystems(StringSet storageSystems) {
_storageSystems = storageSystems;
setChanged("storageSystems");
}
@Name("storageSystems")
@RelationIndex(cf = "RelationIndex", type = StorageSystem.class)
@IndexByKey
public StringSet getStorageSystems() {
return _storageSystems;
}
public void setDecommissionedSystems(StringSet decommissionedSystems) {
_decommissionedSystems = decommissionedSystems;
setChanged("decommissionedSystems");
}
@Name("decommissionedSystems")
public StringSet getDecommissionedSystems() {
return _decommissionedSystems;
}
@Name("description")
public String getDescription() {
return _description;
}
public void setDescription(String description) {
_description = description;
setChanged("description");
}
@Name("manufacturer")
public String getManufacturer() {
return _manufacturer;
}
public void setManufacturer(String manufacturer) {
_manufacturer = manufacturer;
setChanged("manufacturer");
}
@Name("version")
public String getVersionString() {
return _versionString;
}
public void setVersionString(String versionString) {
_versionString = versionString;
setChanged("version");
}
public void setProviderID(String providerID) {
_providerID = providerID;
setChanged("providerID");
}
/**
* AlternateIDIndex - ProviderID (IPAddress-portNumber)
* RelationIndex - Empty
*
* The reason why IPAddress is not used :
* IPAddress is being used as a AltId in StorageSystem.
* If we use IPAddress again in SMISProvider, we would
* end up having the below Rowkey in AltIdIndex ColumnFamily
*
* 10.24.54.32 - RowKey(IPAddress)
* Column : urn:SMISProvider:8178828323..
* Column : urn:StorageSystem:898341992..
*
* Same key , includes both SMISProvider and StorageSystem, and we
* don't want this.
*
*/
@Name("providerID")
@AlternateId("AltIdIndex")
public String getProviderID() {
return _providerID;
}
@EnumType(ConnectionStatus.class)
@Name("connectionStatus")
public String getConnectionStatus() {
return _connectionStatus;
}
public void setConnectionStatus(String connectionStatus) {
_connectionStatus = connectionStatus;
setChanged("connectionStatus");
}
@EnumType(InterfaceType.class)
@Name("interfaceType")
@AlternateId("AltIdIndex")
public String getInterfaceType() {
return _interfaceType;
}
public void setInterfaceType(String interfaceType) {
_interfaceType = interfaceType;
setChanged("interfaceType");
}
@EnumType(DataCollectionJobStatus.class)
@Name("scanStatus")
public String getScanStatus() {
return _scanStatus == null ? DataCollectionJobStatus.CREATED.toString() : _scanStatus;
}
public void setScanStatus(String scanStatus) {
_scanStatus = scanStatus;
setChanged("scanStatus");
}
public void setLastScanStatusMessage(String statusMessage) {
_lastScanStatusMessage = statusMessage;
setChanged("lastScanStatusMessage");
}
@Name("lastScanStatusMessage")
public String getLastScanStatusMessage() {
return _lastScanStatusMessage;
}
@Name("lastScanTime")
public Long getLastScanTime() {
return _lastScanTime;
}
public void setLastScanTime(Long lastScanTime) {
_lastScanTime = lastScanTime;
setChanged("lastScanTime");
}
@Name("nextScanTime")
public Long getNextScanTime() {
return _nextScanTime;
}
public void setNextScanTime(Long nextScanTime) {
_nextScanTime = nextScanTime;
setChanged("nextScanTime");
}
@EnumType(RegistrationStatus.class)
@Name("registrationStatus")
public String getRegistrationStatus() {
return _registrationStatus;
}
public void setRegistrationStatus(String registrationStatus) {
_registrationStatus = registrationStatus;
setChanged("registrationStatus");
}
@EnumType(CompatibilityStatus.class)
@Name("compatibilityStatus")
public String getCompatibilityStatus() {
return _compatibilityStatus;
}
public void setCompatibilityStatus(String compatibilityStatus) {
_compatibilityStatus = compatibilityStatus;
setChanged("compatibilityStatus");
}
@Name("successScanTime")
public Long getSuccessScanTime() {
return _successScanTime;
}
public void setSuccessScanTime(Long time) {
_successScanTime = time;
setChanged("successScanTime");
}
public enum GlobalKeys {
SIO_CLI
}
@Name("keys")
public StringMap getKeys() {
return keys;
}
public String getKeyValue(String key) {
String value = null;
if (keys != null) {
value = keys.get(key);
}
return (value == null) ? NullColumnValueGetter.getNullStr() : value;
}
public void setKeys(StringMap keys) {
this.keys = keys;
setChanged("keys");
}
public void addKey(String key, String value) {
if (getKeys() == null) {
setKeys(new StringMap());
}
getKeys().put(key, value);
setChanged("keys");
}
public void removeKey(String key) {
if (keys != null) {
getKeys().remove(key);
setChanged("keys");
}
}
public void removeKeys(String[] keyArray) {
if (keys != null) {
for (String key : keyArray)
{
getKeys().remove(key);
}
setChanged("keys");
}
}
@Name("nativeId")
public String getNativeId() {
return _nativeId;
}
public void setNativeId(String nativeId) {
_nativeId = nativeId;
setChanged("nativeId");
}
public void addStorageSystem(DbClient dbClient, StorageSystem storage, boolean activeProvider) throws DatabaseException {
if (activeProvider) {
storage.setSmisProviderIP(getIPAddress());
storage.setSmisPortNumber(getPortNumber());
storage.setSmisUserName(getUserName());
storage.setSmisPassword(getPassword());
storage.setSmisUseSSL(getUseSSL());
storage.setActiveProviderURI(getId());
}
if (storage.getProviders() == null) {
storage.setProviders(new StringSet());
}
storage.getProviders().add(getId().toString());
dbClient.persistObject(storage);
if (getStorageSystems() == null) {
setStorageSystems(new StringSet());
}
getStorageSystems().add(storage.getId().toString());
dbClient.updateAndReindexObject(this);
}
public void removeStorageSystem(DbClient dbClient, StorageSystem storage) throws DatabaseException {
if (storage.getProviders() != null) {
storage.getProviders().remove(getId().toString());
}
if (storage.getActiveProviderURI().equals(getId())) {
if (null != storage.getProviders() && !storage.getProviders().isEmpty()) {
Iterator<String> iter = storage.getProviders().iterator();
if (iter.hasNext()) {
try {
storage.setActiveProviderURI(new URI(iter.next()));
} catch (URISyntaxException ex) {
logger.error("URISyntaxException occurred: {}", ex.getMessage());
}
}
else {
storage.setActiveProviderURI(null);
}
}
}
dbClient.persistObject(storage);
if (getStorageSystems() != null) {
getStorageSystems().remove(storage.getId().toString());
}
dbClient.persistObject(this);
}
public void removeDecommissionedSystem(DbClient dbClient, String systemNativeGuid) {
List<URI> oldResources = dbClient.queryByConstraint(AlternateIdConstraint.Factory
.getDecommissionedResourceNativeGuidConstraint(systemNativeGuid));
if (oldResources != null) {
for (URI decomObj : oldResources) {
_decommissionedSystems.remove(decomObj.toString());
}
dbClient.persistObject(this);
}
}
public boolean connected() {
return ConnectionStatus.valueOf(_connectionStatus) == ConnectionStatus.CONNECTED;
}
public boolean initializing() {
return ConnectionStatus.valueOf(_connectionStatus) == ConnectionStatus.INITIALIZING;
}
}