# @file ssh.py
#
# @brief This class is used to execute commands by SSH
#
# @author Manuel Castilla
# @date 05/04/2019
#
###########################################################################

import paramiko
import os
import time
import warnings
warnings.filterwarnings(action='ignore',module='.*paramiko.*')


class SshCmdException (ValueError):
	def __init__(self, arg):
		self.strError = arg
		self.args = {arg}


## Class SshCmd
#  This class implements the snmpcmd command, used to send an
#  SSH command to the target device.
class SshCmd ():
	def __init__(self,timeWait=10):
		"""
		Constructor

		Args:
			timeWait: max time wait to execute commands

		"""
		self.timeWaitResponse = timeWait
		self.ssh = None

	def __del__(self):
		"""
		Destructor
		"""
		if (self.ssh != None):
			self.ssh.close()

	def exec(self,dev,command,user,passw=None,withResponse=True):
		"""
		Execute a command

		Args:
			dev: ip or hostname
			command: command to execute
			user: username
			passw : password
			withResponse: indicates if the command has a response
		Raises:
			SshCmdException
		Return:
			command result
		"""
		resp = ""

		try:
			self.ssh = paramiko.SSHClient()
			self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
			self.ssh.connect(dev, username=user, password=passw,timeout=5)
		except paramiko.AuthenticationException as error:
			self.ssh.close()
			raise SshCmdException("ssh failed autentication")
		except:
			self.ssh.close()
			raise SshCmdException("ssh not connection")

		# Send the command (non-blocking)
		stdin, stdout, stderr = self.ssh.exec_command(command,get_pty=True)
		stdin.close()
		stderr.close()

		if (withResponse):
			# Wait for the command to terminate
			i = 0
			while not stdout.channel.exit_status_ready():
				if i == self.timeWaitResponse:
					stdout.channel.close()
					stdout.close()
					self.ssh.close()
					raise SshCmdException("Not return command")
				i = i + 1
				time.sleep(1)

			# Only print data if there is data to read in the channel
			if stdout.channel.recv_exit_status() == 0:
				resp = stdout.read().decode('utf-8')
			else:
				resp = stdout.read().decode('utf-8')
				stdout.channel.close()
				stdout.close()
				self.ssh.close()
				raise SshCmdException(resp)

			#Close fds
			stdout.channel.close()
			stdout.close()
			self.ssh.close()

		return resp

	def printSshErrorCommand(self,sshError,command = None):
		"""
		Print error command

		Args:
			sshError: error message
			command: cammand executed
		"""
		if command != None:
			print("Ssh error:",sshError,"Command:",command)
		else:
			print("Ssh error:",sshError)
