import logging
import string
import random
import pipes

from parallels.common.utils import unix_utils
from parallels.common.utils.ssh_utils import ExecutionError

# H-Sphere puts 'cpanel' user's SSH public key to all remote nodes to have an access to them.
# As it is not guaranteed that we have a direct SSH access to all H-Sphere remote nodes
# from a box with migrator tool, we:
# 1) go to H-Sphere CP server by SSH 
# 2) "login" as 'cpanel' user
# 3) use its SSH key to access all remote nodes

class HsphereRunner:
	logger = logging.getLogger(__name__)
	
	def __init__(self, ssh_runner, ip):
		self.ssh_runner = ssh_runner
		self.ip = ip
	
	def sh(self, cmd_str, args=None, stdin_content=None):
		formated_cmd = self._format_command(cmd_str, args)
		if stdin_content is not None:
			return self.ssh_runner.sh("""su - cpanel -c "ssh root@%s '%s'" """ % (self.ip, formated_cmd), None, stdin_content)
		self.logger.debug(u"Execute remote command as multiline command.")
		return self.ssh_runner.sh("su - cpanel", None, u"ssh -o StrictHostKeyChecking=no -o GSSAPIAuthentication=no root@%s %s" % (self.ip, pipes.quote(formated_cmd)))
	
	def sh_unchecked(self, cmd_str, args=None, stdin_content=None):
		formated_cmd = self._format_command(cmd_str, args)
		if stdin_content is not None:
			return self.ssh_runner.sh_unchecked("""su - cpanel -c "ssh -o StrictHostKeyChecking=no -o GSSAPIAuthentication=no root@%s '%s'" """ % (self.ip, formated_cmd), None, stdin_content)
		self.logger.debug(u"Execute remote command as multiline command.")
		return self.ssh_runner.sh_unchecked("su - cpanel", None, u"ssh -o StrictHostKeyChecking=no -o GSSAPIAuthentication=no root@%s %s" % (self.ip, pipes.quote(formated_cmd)))
		
	def _format_command(self, cmd_str, args):
		""" Due to such construction does not support multiline cmd and stdin
			we switch type of command execution for multiline cmd and multiline stdin  
		"""
		if args is not None:
			cmd_str = unix_utils.format_command(cmd_str, **args)
		self.logger.debug(u"Execute '%s' command on H-sphere, ip: '%s'." % (cmd_str, self.ip))
		return cmd_str
		
	def run(self, cmd, args=[], stdin_content=None):
		exit_status, stdout_content, stderr_content = self.run_unchecked(cmd, args, stdin_content)
		if exit_status != 0:
			raise ExecutionError(cmd, exit_status, stdout_content, stderr_content)
		else:
			return stdout_content
	
	def run_unchecked(self, cmd, args=[], stdin_content=None):
		cmd_str = " ".join([
			pipes.quote(arg) for arg in [cmd] + args 
		])
		self.logger.debug(u"Execute '%s' command on H-sphere, ip: '%s'." % (cmd, self.ip))
		return self.ssh_runner.sh_unchecked("su - cpanel", None, u"ssh -o StrictHostKeyChecking=no -o GSSAPIAuthentication=no root@%s '%s'" % (self.ip, cmd_str))

	def run_script(self, script, stdin_content=None):
		def rand_str(size=6, chars=string.ascii_uppercase + string.digits):
			return ''.join(random.choice(chars) for x in range(size))
		
		script_temp_filename = '/tmp/temp_script.' + rand_str(5)
		stdin_temp_filename = '/tmp/temp_stdin.' + rand_str(5)
		
		self.logger.debug(u"Load script content to Hsphere, ip: '%s'." % (self.ip))
		self.sh(u"cat > %s" % (script_temp_filename), None, stdin_content=script)
		
		if stdin_content is not None:
			self.logger.debug(u"Load stdin content to Hsphere, ip: '%s'." % (self.ip))
			self.sh(u"cat > %s" % (stdin_temp_filename), stdin_content=stdin_content)

		self.logger.debug(u"Execute script on Hsphere, ip: '%s'." % (self.ip))
		ret = None
		if stdin_content is not None:
			ret = self.sh(u"cat %s | /bin/sh %s" % (stdin_temp_filename, script_temp_filename))
		else:
			ret = self.sh(u"/bin/sh %s" % (script_temp_filename))

		self.logger.debug(u"Remove temp files from Hsphere, ip: '%s'." % (self.ip))
		self.sh(u"rm -rf %s" % script_temp_filename)
		if stdin_content is not None:
			self.sh(u"rm -rf %s" % stdin_temp_filename)
		
		return ret
	
	def remove_file(self, filename):
		return self.run('/bin/rm', [filename])
