from parallels.core.logging import get_logger
from parallels.core import messages
from parallels.core.connections.ssh.lazy_open_ssh_connection import LazyOpenSSHServerConnection
from parallels.core.utils.common import cached

logger = get_logger(__name__)


class SSHConnectionPool(object):
    """SSH connection pool - factory for SSH connections to servers"""

    @staticmethod
    @cached
    def get_instance():
        """Single instance for SSHConnectionPool

        :rtype : SSHConnectionPool
        """
        return SSHConnectionPool()

    def __init__(self):
        self._connections = {}
        self.readonly = False

    def get(self, ssh_settings, server):
        """Get SSH connection for specified parameters

        :param ssh_settings - object with SSH connection
        parameters (IP address, credentials).
        :param server - server object
        :rtype: parallels.core.connections.ssh.server_connection.lazy_open.LazyOpenSSHServerConnection
        """
        if self.readonly:
            raise Exception(messages.ALL_SSH_CONNECTIONS_WERE_ALREADY_CLOSED)

        key = self._key(ssh_settings)
        if key not in self._connections:
            self._connections[key] = LazyOpenSSHServerConnection(
                ssh_settings, server
            )
        return self._connections[key]

    def close_all(self):
        """Finalize - close all opened SSH connections

        :rtype None
        """

        for connection in self._connections.values():
            logger.debug(messages.DEBUG_CLOSE_SSH_CONNECTION, connection.node_description)
            connection.close()
        self.readonly = True

    @staticmethod
    def _key(ssh_settings):
        return (
            ssh_settings.ip,
            ssh_settings.ssh_auth.username
        )
