/* * Copyright 2016 Dell Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.emc.storageos.driver.dellsc.helpers; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.driver.dellsc.DellSCDriverException; import com.emc.storageos.driver.dellsc.scapi.StorageCenterAPI; import com.emc.storageos.driver.dellsc.scapi.StorageCenterAPIException; import com.emc.storageos.driver.dellsc.scapi.objects.StorageCenter; import com.emc.storageos.storagedriver.Registry; /** * Handles persistence for driver data. */ public class DellSCConnectionManager { private static final Logger LOG = LoggerFactory.getLogger(DellSCConnectionManager.class); private static final String DRIVER_NAME = "dellscsystem"; private static final String HOST_KEY = "HOST"; private static final String PORT_KEY = "PORT"; private static final String USER_KEY = "USER"; private static final String PASS_KEY = "PASS"; private static final Object lockObj = new Object(); private static DellSCConnectionManager instance; Map<String, StorageCenterAPI> connectionMap; Map<String, String> systemLookup; private Registry driverRegistry; /** * Private constructor. */ private DellSCConnectionManager() { connectionMap = new HashMap<>(); systemLookup = new HashMap<>(); } /** * Get the instance. * * @return The DellSCConnectionManager instance. */ public static DellSCConnectionManager getInstance() { synchronized (lockObj) { if (instance == null) { instance = new DellSCConnectionManager(); } } return instance; } /** * Sets the persistence store. * * @param driverRegistry The driver persistence registry. */ public void setDriverRegistry(Registry driverRegistry) { this.driverRegistry = driverRegistry; } /** * Saves connection information to the registry. * * @param systemId The identifier for this entry. * @param host The host name or IP. * @param port The connection port. * @param user The connection user name. * @param password The connection password. */ public void saveConnectionInfo(String systemId, String host, int port, String user, String password) { LOG.info("Saving connection information for {} - {}:{}", systemId, host, port); List<String> listHost = new ArrayList<>(); List<String> listPort = new ArrayList<>(); List<String> listUser = new ArrayList<>(); List<String> listPass = new ArrayList<>(); listHost.add(host); listPort.add(Integer.toString(port)); listUser.add(user); listPass.add(password); Map<String, List<String>> attributes = new HashMap<>(); attributes.put(HOST_KEY, listHost); attributes.put(PORT_KEY, listPort); attributes.put(USER_KEY, listUser); attributes.put(PASS_KEY, listPass); this.driverRegistry.clearDriverAttributesForKey(DRIVER_NAME, systemId); this.driverRegistry.setDriverAttributesForKey(DRIVER_NAME, systemId, attributes); } /** * Get a connection from the saved settings. * * @param systemId The system ID of the connection. * @return The Storage Center API connection. * @throws DellSCDriverException on failure. */ public StorageCenterAPI getConnection(String systemId) throws DellSCDriverException { LOG.info("Getting saved connection information for {}", systemId); String key = systemLookup.get(systemId); if (key == null) { // Old connection information key = systemId; } try { Map<String, List<String>> connectionInfo = this.driverRegistry.getDriverAttributesForKey( DRIVER_NAME, key); return getConnection( connectionInfo.get(HOST_KEY).get(0), Integer.parseInt(connectionInfo.get(PORT_KEY).get(0)), connectionInfo.get(USER_KEY).get(0), connectionInfo.get(PASS_KEY).get(0), false); } catch (Exception e) { LOG.error(String.format("Error getting saved connection information: %s", e), e); throw new DellSCDriverException("Error getting saved connection information.", e); } } /** * Gets a new Storage Center API connection. * * @param host The host name or IP. * @param port The connection port. * @param user The connection user name. * @param password The connection password. * @param isProvider The isProvider flag to indicate the provider call * @return The API connection. * @throws StorageCenterAPIException */ @SuppressWarnings("resource") public StorageCenterAPI getConnection(String host, int port, String user, String password, boolean isProvider) throws StorageCenterAPIException { // First see if we already have a connection for this system StorageCenterAPI result = connectionMap.get(host); if (result == null) { result = StorageCenterAPI.openConnection( host, port, user, password); StorageCenter[] scs = result.getStorageCenterInfo(); for (StorageCenter sc : scs) { // Saving per system for backward compatibility saveConnectionInfo(sc.scSerialNumber, host, port, user, password); systemLookup.put(sc.scSerialNumber, host); } saveConnectionInfo(host, host, port, user, password); connectionMap.put(host, result); } else { // Make sure our connection is still good result = validateConnection(result, result.getHost()); /* * Update the SC Connection Info only during storage provider discovery * bugfix-COP-25081-dell-sc-fail-to-recognize-new-arrays */ if(isProvider) { StorageCenter[] scs = result.getStorageCenterInfo(); for (StorageCenter sc : scs) { // Saving per system for backward compatibility saveConnectionInfo(sc.scSerialNumber, host, port, user, password); systemLookup.put(sc.scSerialNumber, host); } } } return result; } /** * Validate that an API connection is still good. * * @param api The API connection. * @param key The connection key. * @return The validated API connection. * @throws StorageCenterAPIException */ private StorageCenterAPI validateConnection(StorageCenterAPI api, String key) throws StorageCenterAPIException { StorageCenterAPI result = api; try { // Make a call to validate the connection is still good. result.getApiConnection(); } catch (StorageCenterAPIException e) { // Something is wrong with that connection, create new one LOG.warn(String.format("Connection failed, attempting to reconnection: %s", e)); Map<String, List<String>> connectionInfo = this.driverRegistry.getDriverAttributesForKey( DRIVER_NAME, key); int port = 3033; try { port = Integer.parseInt(connectionInfo.get(PORT_KEY).get(0)); } catch (NumberFormatException nex) { LOG.warn(String.format("Invalid port setting: %s", connectionInfo.get(PORT_KEY).get(0))); } result = StorageCenterAPI.openConnection( connectionInfo.get(HOST_KEY).get(0), port, connectionInfo.get(USER_KEY).get(0), connectionInfo.get(PASS_KEY).get(0)); connectionMap.put(api.getHost(), result); } return result; } }