+ try:
+ start = time()
+ pkey = None
+ if 'priv_key' in node:
+ pkey = RSAKey.from_private_key(
+ StringIO.StringIO(node['priv_key']))
+
+ self._ssh = SSHClient()
+ self._ssh.set_missing_host_key_policy(AutoAddPolicy())
+
+ self._ssh.connect(node['host'], username=node['username'],
+ password=node.get('password'), pkey=pkey,
+ port=node['port'])
+
+ self._ssh.get_transport().set_keepalive(10)
+
+ SSH.__existing_connections[node_hash] = self._ssh
+ logger.debug('New SSH to {peer} took {total} seconds: {ssh}'.
+ format(
+ peer=self._ssh.get_transport().getpeername(),
+ total=(time() - start),
+ ssh=self._ssh))
+ except SSHException:
+ raise IOError('Cannot connect to {host}'.
+ format(host=node['host']))
+ except NoValidConnectionsError as err:
+ logger.error(repr(err))
+ raise IOError('Unable to connect to port {port} on {host}'.
+ format(port=node['port'], host=node['host']))
+
+ def disconnect(self, node=None):
+ """Close SSH connection to the node.
+
+ :param node: The node to disconnect from. None means last connected.
+ :type node: dict or None
+ """
+ if node is None:
+ node = self._node
+ if node is None:
+ return
+ node_hash = self._node_hash(node)
+ if node_hash in SSH.__existing_connections:
+ logger.debug('Disconnecting peer: {host}, {port}'.
+ format(host=node['host'], port=node['port']))
+ ssh = SSH.__existing_connections.pop(node_hash)
+ ssh.close()
+
+ def _reconnect(self, attempts=0):
+ """Close the SSH connection and open it again.
+
+ :param attempts: Number of reconnect attempts.
+ :type attempts: int
+ """
+ node = self._node
+ self.disconnect(node)
+ self.connect(node, attempts)
+ logger.debug('Reconnecting peer done: {host}, {port}'.
+ format(host=node['host'], port=node['port']))