from parallels.core import messages
import logging

from parallels.core.connections.ssh.server_connection.lazy_open \
	import LazyOpenSSHServerConnection
from parallels.core.utils.common import cached

logger = logging.getLogger(__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, node_description):
		"""Get SSH connection for specified parameters

		:param ssh_settings - object with SSH connection
		parameters (IP address, credentials).
		:param node_description - string human-readable description of the server
		:rtype: parallels.core.connections.ssh.server_connection.base.BaseSSHServerConnection
		"""
		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, node_description
			)
		return self._connections[key]

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

		:rtype None
		"""

		for connection in self._connections.itervalues():
			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
		)
